简介
Python中,在数据处理这方面最流行的包应当是属于Pandas了。Pandas与Scipy一样,都是基于NumPy这个包开发出来的,所以使用时,都需要引用Numpy。Pandas中的DataFrame与R语言中的数据框的设计理念基本是一致的。不光如此,除了是DataFrame数据类型以外,Pandas还提供时间序列类型Series,以及面板类型Panel。
import numpy as np
import pandas as pd
from pandas import Series, DataFrame, Panel
接下来,我们先来介绍一下Pandas的基本使用方法,然后再根据前一讲用Pandas进行实现,数据类型主要介绍DataFrame。下面的实现,默认以及按上述代码导入np以及pd、DataFrame等。
正文
一,Pandas介绍
1,I/O 数据的导入与导出
(1) 利用pandas的函数导入数据
read_csv() / read_table() 的详细参数
逐块读入数据示例
chunker = pd.reade_csv(path, chunksize = 100)
tot = Serise([])
for piece in chunker :
tot = tot.add(piece[‘key’],value_counts(), fill_value= 0)
tot = tot.order(ascending=False)
(2) 利用pandas.DataFrame导出数据
2, 数据的索引与筛选
(1) pandas 会为你自动从0生成索引值
DataFrame是一个表格型的数据结构,它含有一组有序的列,每列可以是不同的值类型(数值,字符串,布尔值等)。可以与Python中的字典类型互转。
data = {'state':['fe','te','eea'],'year':[2018,2017,2016],'avgage':[87,85,89]}
frame = DataFrame(data)
print frame
数据中,默认的0,1,2即为自动生成的索引值。
|avgage | state | year
0 | 87 | fe | 2018
1 | 85 | te | 2017
2 | 89 | eea | 2016
(2) 根据索引选取数据
- 通过冒号选取行
例:frame[:2]
- 通过布尔数组选取行
例:frame[frame['year']==2018]
- 通过列索引选取列
例:frame[ 'year', 'state'] ]
- 通过ix选取,(或 iloc操作相同)
选取某行:obj.ix[val]
选取某列:obj.ix[ : , val]
同时选中某行和某列:obj.ix[ val1, val2 ]
3,数据的函数应用
Numpy的通用函数ufunc是可用于pandas,此外,另外我们还可以使用下面几种常用的方式,详细点击此处查看详情。
- DataFrame.apply()
- DataFrame.applymap()
- DataFrame.aggregate()
- DataFrame.transform()
例:
自定义一极差函数:f = lambda x: x.max() -x.min()
计算每列的极差值: frame.apply(f, axis = 1)
下面列出一些常用的自带函数
4,数据缺失的处理
我们把之前的例子改一下,通过np.nan来赋值缺失值。
data = {'state':['fe',np.nan,'eea'],'year':[2018,2017,2016],'avgage':[87,85,np.nan]}
frame = DataFrame(data,columns=['year','state','avgage'])
print frame
(1) 查看哪些元素有缺失值isnull()frame.isnull()
返回值如下
year state avgage
0 False False False
1 False True False
2 False False True
(2)count统计,忽略NaNframe.count()
统计时,会跳过NaN
类似的,还有sum()等
(3)fillna填充缺失值
- 所有缺失值,填充为统一值(数值或字符均可)
例,所有缺失值填充为0:frame.fillna(0)
- 限制填充缺失值
例,选取state列,仅填充第一个缺失值:frame['state'].fillna(0, limit=1)
5,合并数据集
pandas自带的数据大体有三个方法
- pd.merge
- pd.join,类似merge简化版
- pd.concat,轴向连接,类似于numpy.concatenate(),默认情况下,concat中的axis=0,表示添加行
pd.merge参数如下
pd.merge(df1, df2, how='innner', on = 'key')
表示:用df1中的key列 与df2中的key列进行内关联,合并取得数据。
pd.merge( df1, df2 , left_on = 'key', right_index = True, how = 'outer')
表示:用df1中的key列 与df2中索引列进行外关联,合并取得数据。
6,数据的聚合与分组运算
DataFrame.groupby()
- 1,根据列分组:dataframe.groupby([列1,列2]).mean()
⚠️分组中的缺失值默认会被排除在外计算 - 2,根据字典或Series分组:dataframe.groupby(字典或Series).mean()
- 3,根据函数分组:dataframe.groupby(len).mean() ,比如根据长度len来分组
- 4,根据索引分组:dataframe.groupby(level=‘city’,axis=1).count()
groupby将会产生一个GroupBy对象,该对象可以进行迭代、运用聚合函数等
可以用groupby对象.agg(func)
, 通过agg使用自己写的的聚合函数func
agg(),可选取多个函数,agg(‘mean’, ‘count’, ’sum’, ’median’, ’std’, ’var’, ’min’, ’max’, ’prod’, ’first’, ’last’ )
二,利用Pandas进行数据预处理
前一节讲过,预处理的四个步骤,接下来演示相应的操作:
数据清洗:SINCE原则处理数据
数据集成:pandas.merge方法
数据变换:pandas、scipy、numpy的处理
数据规约:会放到第五章进行讲解
1,数据清洗
- Simple原则: 发现重复与冗余
data = {'state':['a','b','c','a','b','c'],'year':[2018,2016,2017,2018,2016,2017],'avgage':[87,85,88,87,85,88]}
frame = DataFrame(data,columns=['year','state','avgage'])
print frame
frame[frame.duplicated()].count() #统计所有数据全部重复的有多少
frame[frame.duplicated()] #统计重复的数据是哪几个
year state avgage
3 2018 a 87
4 2016 b 85
5 2017 c 88
frame.drop_duplicates() #把重复的删除,但是不会删除原始数据
对于冗余,与数据规约的步骤是基本一致的,会合并到数据规约的步骤来计算。
- Integral原则:处理缺失处理
处理缺失值的具体理论方法,参见第六章,此处仅介绍一下,如何发现以及填充缺失值。
data = {'state':['a','b','c',np.nan,'b','c'],'year':[2018,2016,np.nan,2018,2016,2017],'avgage':[87,85,88,np.nan,85,88]}
frame = DataFrame(data,columns=['year','state','avgage'])
print frame
frame.count() # 统计了每列剔除缺失值以后的个数
frame.isnull().sum() # 统计了每列缺失值的个数
frame.fillna(0) #把缺失值都填充为0,此处也可以是字符串,不过很少有把缺失值填充统一值的
对于不同的列,动态指定不同列的填充值
frame.fillna(frame.mean()) # 将每一列的均值填充到各列自己的缺失值中,同理最大最小值等统计值均可。
# 可以看到,只有数值型的列,适合用均值这种统计指标,对于列state, 我们可以用频数高的众数
# 当然众数可能不是唯一的,所以我们取第一个众数,来填充state列
frame['state'].fillna(frame.mode()['state'][0])
# 运用自定义函数来填充, 假设自定义函数就是取众数的第一个值
f = lambda x: x.fillna(x.mode()[0])
frame.apply(f)
- Normal原则:统一格式并标准化
统一格式,基本就是修改并赋值的过程,此处不再讨论。
对于数值型变量,我们有两种方式,标准化:
归一化公式
f = lambda x: ( x - min(x) )/ ( max(x) - min(x) )
frame['avgage'].transform(f)
标准化公式
f = lambda x: ( x - x.mean() )/ x.std()
frame['avgage'].transform(f)
- Consistent一致性原则:就要以业务与经验为主来判断
- Effective有效原则:错误与异常
对于异常值,我们最简单的方法是查看样本数据的分布来得到结果。根据箱线图的三个重要的分位数,在Q3+1.5IQR和Q1-1.5IQR的范围以外的,认为是异常值,或者叫做离群点。
q1, q2, q3 = frame['avgage'].quantile([0.25,0.5,0.75])
IQR = q3-q1
O1 = q1 - 1.5*IQR
O2 = q3 + 1.5*IQR
(frame['avgage'] < O1) | (frame['avgage'] > O2 ) # 是否异常点的判断
此外,还有专门研究异常检测的方法论,可以参照第十八章异常检测,来进行学习。
2,数据集成:
pandas.merge方法
dat1 = DataFrame({'key':['a','b','d'],
'value1':[12,3,5],
'year':[1998,1999,2001]})
dat2 = DataFrame({'key':['a','c','e'],
'value2':[43,32,10],
'mon':[12,10,10]})
# 通过key值内关联起来
pd.merge(dat1,dat2,on = 'key',how='inner')
key value1 year mon value2
0 a 12 1998 12 43
# 通过key值左关联起来
pd.merge(dat1,dat2,on = 'key',how='left') # 或
pd.merge(dat1,dat2,left_on = 'key',right_on = 'key',how='left')
key value1 year mon value2
0 a 12 1998 12.0 43.0
1 b 3 1999 NaN NaN
2 d 5 2001 NaN NaN
3,数据变换:
将数值属性拆分成分类属性
dat = DataFrame({'value':[12,3,5,3,5,6,7,8,2,5,8,1,4,8]})
#将数据分为三组,并且命名组1、2、3;
result = pd.cut(dat['value'],3,labels=['组1','组2','组3'])
#将分组变量dummy化
dum = pd.get_dummies(result)
#合并这些结果
pd.concat([dat,result,dum],axis=1)