pandas统计分析基础知识及练习题
个人博客页面(有附件):pandas统计分析基础知识及练习题
1、读取不同数据源的数据
(1)数据库数据读取
pandas提供了读取与存储关系型数据库数据的函数和方法,除此之外还需要使用SQLAIchemy库建立对应的数据库连接。使用create_engine函数建立数据库连接。
import pandas as pd
from sqlalchemy import create_engine
engin = create_engine('mysql+pymysql://root:mysql@127.0.0.1:3306/datafenxi?charset=utf8')
# 数据库产品名称+连接工具名://用户名:密码@数据库IP地址:端口号/数据库名称?charset=数据库编码
data = pd.read_sql_table('meal_order_detail1', con=engin)
data1 = pd.read_sql_query('select * from meal_order_detail1', con=engin)
data2 = pd.read_sql('meal_order_detail1', con=engin)
data3 = pd.read_sql('select * from meal_order_detail1', con=engin)
使用pandas进行数据库的读取:
函数名 | 说明 |
---|---|
read_sql_table | 只能读取数据库的某一个表格,不能实现查询操作 |
read_sql_query | 只能实现查询操作,不能直接读取数据库中的某个表 |
read_sql | 是上面两个函数的结合,能够读取数据库中的表,并且能够实现查询操作 |
pandas三个数据库操作函数所具有的参数基本一致,区别在于输入的是表名还是语句。
参数名 | 说明 |
---|---|
sql 或 table_name | 接受string,表示读取的数据的表名或语句,无默认 |
con | 接收数据库连接,表示数据库连接信息,无默认 |
index_col | 接收int,sequence或False。表示设定的列作为行名,如果是一个数列则是多重索引。默认为None。 |
coerce_float | 接收boolean。将数据库中的decimal类型的数据转化为pandas中的float64类型的数据。默认为True。 |
columns | 接收list。表示读取数据库的列名,默认为None。 |
pandas的数据库操作中数据存储只有一个方法为 to_sql 方法
(2)读写文本文件
import pandas as pd
data = pd.read_table('./data/job_info.csv', encoding='gbk', sep=',')
data1 = pd.read_csv('./data/job_info.csv')
csv文件是一种逗号分隔符的文件格式,又被称为字符分隔文件,是以纯文本形式存储表格数据
使用 read_table 来读取文本文件
使用 read_csv 来读取csv文件
常用参数说明:
参数名 | 说明 |
---|---|
filepath | 接受string,代表文件路径,无默认 |
sep | 接受string,代表分隔符。read_table默认为制表符,read_csv默认为“,”。 |
header | 接受int或sequence。表示将某行数据作为列名,默认为infer(自动识别) |
names | 接受array,表示列名。默认为None. |
index_col | 接受int、sequence或Flase。表示索引列的位置,取值为sequence则代表多重索引。默认为None |
dtype | 接受dict。代表写入的数据类型(列名为Key,数据格式为Value),默认为None |
engine | 接受C或者python。代表数据解析引擎,默认为C |
文本文件的存储是通过pandas中的 to_csv 函数实现的(以csv文件格式存储)
(3)读写excel文件
import pandas as pd
data = pd.read_excel('./data/chipotle.xlsx')
pandas可以读取“xls”和“xlsx”两种Excel文件,使用的是 read_excel 方法。
具有参数:
参数名 | 说明 |
---|---|
io | 接收string。表示文件路径 |
sheetname | 接收string,int。代表excel表内分表位置。默认为0 |
header | 接收int或sequence。表示将某行数据作为列名,默认为infer(自动识别) |
names | 接收int,sequence或False。表示索引列位置,默认为None |
index_col | 接收int,sequence或False。表示索引列位置,默认为None |
dtype | 接收dict。代表写入的数据类型,默认为None |
将文件存储为excel文件时可以使用 to_excel 方法
2、掌握DataFrame的常用操作
DataFrame的基本属性
函数名 | 返回值 |
---|---|
values | 元素 |
index | 索引 |
columns | 列名称 |
dtypes | 数据类型 |
size | 元素个数 |
ndim | 维度 |
shape | 数据的形状(行数×列数) |
数据查看基本方法,DataFrame是一个带有标签的二维数组,每一个标签都作为了这一列的列名。
可以使用两种方式进行数据访问。
- 以字典的方式使用某一列名,实现单列数据访问。
- 以属性的方式访问,实现单列数据访问(不建议使用,容易引起混淆)
import pandas as pd
data = pd.read_excel('./data/chipotle.xlsx')
print(data['quantity']) # 对quantity这一列进行数据访问
print(data[['order_id', 'item_name']]) # 对order_id 及 item_name 两列进行数据访问
print(data['quantity'][:5])# 对quantity这一列前5行进行数据访问
loc 及 iloc 切分方法
import pandas as pd
data = pd.read_excel('./data/chipotle.xlsx')
print(data.iloc[2:5, 2])
print(data.loc[2:5, 'item_name'])
loc及iloc访问方式,loc方法是针对DataFrame索引名称的切片方法,如果传入的不是索引名称,那么切片操作将无法执行。利用loc方法,能够实现所有单层索引切片操作。iloc和loc区别是iloc接受的必须是行索引和列索引的位置。
- DataFrame.loc[行索引名称或条件,列索引名称]
- DataFrame.iloc[行索引位置,列索引位置]
使用loc方法和iloc实现多列切片,其原理通俗的说就是将多列的列名或者位置作为一个列表或者数据传入。这两个方法可以取出DataFrame中的任意数据。在使用loc的时候内部传入的行索引名称如果为一个区间,则前后均为闭区间,iloc方法使用时内部传入的行索引位置或列索引位置为区间时,则为前闭后开区间。loc内部还可以传入表达式,结果返回满足表达式的所有值。
ix 切片方法
import pandas as pd
data = pd.read_excel('./data/chipotle.xlsx')
print(data.ix[2, 2])
print(data.ix[2, 'item_name'])
可以使用ix方法进行切片,ix方法更像是loc和iloc两种方法的结合,ix方法在使用时既可以接受索引名称也可以接受索引位置。
- DataFrame.ix[行索引的名称、位置或条件,列索引名称或位置]
使用ix方法需要注意几点:
- 在使用ix参数时,尽量保持行索引名称和行索引位置重叠,使用时就无需考虑取值时区间的问题。(一律为闭区间)
- 使用列索引名称,而非列索引位置。主要用来保证代码可读性。
- 使用列索引位置时,需要注解。同样保证代码可读性
- ix具有一个缺点,在面对数据量巨大的任务时,其效率会低于loc和iloc方法,所以日常使用时建议使用iloc和loc方法切片。
增添数据
DataFrame添加一列数据,只需新建一个列索引,并对该索引下的数据进行赋值操作即可。新增的一列值是相同的则直接赋值一个常量即可。
删除数据
删除某列或某行数据需要用到pandas中的drop方法。
- drop(labels, axis=0, level=None, inplace=False, errors='raise')
参数名 | 说明 |
---|---|
labels | 接收string或array。代表要删除的行或列,无默认。 |
axis | 接收0或1。0表示删除行,1表示删除列。 |
level | 接收int或索引名。代表标签所在级别,默认None |
inplace | 接收boolean。代表操作是否对源数据生效。 |
数值型特征的描述性统计
pandas基于Numpy库,可以使用这些函数对数据框进行描述性统计。
函数名 | 说明 |
---|---|
np.min | 最小值 |
np.max | 最大值 |
np.mean | 平均值 |
np.ptp | 极值 |
np.median | 中位数 |
np.std | 标准差 |
np.var | 方差 |
np.cov | 协方差 |
pandas还提供了一个方法叫做 describe,能够一次性得出数据框所有数值型特征的非空值数目、均值、四分位数、标准差。
类别型特征的描述性统计
描述类别型特征的分布状况,可以使用频数统计表。pandas库中实现频数统计的方法为value_counts。
pandas还提供了categories类,可以使用astype方法将目标特征的数据类型转换为category类别。
describe方法除了支持传统数值型以外,还能够支持对category类型的数据进行描述型统计,四个统计量分别为列非空元素的数目、类别的数目、数目最多的类别、数目最多类别的数目。
3、转换与处理时间序列数据
在多数情况下,对数据类型数据进行分析的前提就是将原本为字符串的时间转换为标准时间类型。pandas继承了Numpy库和datatime库的时间相关模块,提供了6中时间相关的类。
类名称 | 说明 |
---|---|
Timestamp | 最基础的时间类,表示某个时间点。在绝大多数情况下的时间数据都是Timestamp形式的时间。 |
Period | 表示单个时间跨度,或者某个时间段。例如,某一天、某一小时等。 |
Timedelta | 表示不同单位的时间,而非具体的某个时间段。例如1天、1小时、2分钟等。 |
DatetimeIndex | 一组Timestamp构成的Index,可以用来作为Series或DataFrame的索引。 |
PeriodtimeIndex | 一组Period构成的Index,可以用来作为Series或DataFrame的索引。 |
TimedeltaIndex | 一组Timedelta构成的Index,可以用来作为Series或DataFrame的索引。 |
其中,Timestamp作为时间类中最基础的,也是最常用的。在多数情况下,时间相关字符串都会转换为Timestamp。pandas也提供了to_datetime函数,能够实现这一目标。Timestamp类型时间是有限制的。
4、练习题
探索快餐数据,完成以下问题(对应数据:chipotle.tsv):
1、将数据集存入一个名为chipo的数据框内
2、查看前10行内容
3、数据集中有多少个列(columns)?
4、打印出全部的列名称
5、数据集的索引是怎样的?
6、被下单数最多的商品(item)是什么?
7、在item_name这一列中,一共有多少种商品被下单?
8、一共有多少个商品被下单?
9、将item_price转换为浮点数
10、在该数据集对应的时期内,收入(revenue)是多少?
11、在该数据集对应的时期内,一共有多少订单?
12、每一单(order)对应的平均总价是多少?
import pandas as pd
# === 第一题 ===
chipo = pd.read_table('./data/chipotle.tsv')
chipo.to_excel('./data/chipotle.xlsx')
# === 第二题 ===
no2 = chipo.head(10)
print("前十行内容如下表所示:\n",no2)
# === 第三题 ===
no3 = chipo.shape
print("一共有:", no3[1], "列")
# === 第四题 ===
no4 = chipo.columns
print("列名称为:", no4)
# === 第五题 ===
no5 = chipo.index
print("索引是:", no5)
# === 第六题 ===
no6 = chipo[['item_name','quantity']].groupby(by=['item_name']).sum().sort_values(by=['quantity'],ascending=False)
print("被下单最多的商品是:\n",no6.head(1))
# === 第七题 ===
no7 = chipo['item_name'].describe()
print("一共有", no7['unique'],"种商品被下单")
# === 第八题 ===
no8 = chipo['quantity'].sum()
print("一共有", no8,"个商品被下单")
# === 第九题 ===
for i in range(len(chipo['item_price'])) :
chipo.loc[i, 'item_price'] = chipo.loc[i, 'item_price'].strip('$')
chipo['item_price'] = pd.to_numeric(chipo['item_price'])
# print(chipo['item_price'])
no9 = chipo['item_price'].dtype
print("更改后的数据类型是:",no9)
# === 第十题 ===
data = chipo.loc[:, ['order_id','quantity','item_price']]
# print(data)
data['row_sum'] = data['quantity'] * data['item_price']
print(data)
revenue = data['row_sum'].sum()
print("在该数据集对应的时期内,收入为",revenue,"$")
# === 第十一题 ===
no11 = chipo['order_id'].nunique()
print("在数据集对应的时期内,一共有",no11,"个订单")
# === 第十二题 ===
no12 = data[['order_id','row_sum']].groupby(by='order_id')
print("每一单对应的平均总价如下表所示:\n",no12.mean())
chipo['item_price_sum'] =chipo['quantity'] * chipo['item_price']
print((chipo[['order_id','item_price_sum']].groupby(by=['order_id']).sum()).mean())
最后,这是我上课时候的内容,练习题是自己的课后作业(非参考答案,参考需谨慎),所以内容肯定不全,也有可能存在错误,欢迎指出错误。
今后可能会继续把上课内容及作业写出来。(大概,不懒的话)
ps:上传了作业需要的文件。