第5章
pandas数据整理
采集到的原始数据通常来自多个异构数据源,数据在准确性、完整性和一致性等方面存
在着多种多样的问题。在数据分析挖掘之前,首先要做的就是对数据进行整理,处理缺失
值、重复值、噪声数据以及规范数据,得到一个高质量的数据集,从而提高数据分析的准确性
和有效性。本章主要介绍数据运算与排序,数据集成,数据筛选,删除指定的行或列,重新命
名列名、行名和重新索引,缺失值处理,异常值处理,重复值处理,数据替换、更新与转换,噪
声数据处理,数据规范化,数据离散化,数据归约,以及数据降维。
5.1 数据运算与排序
5.1.1 数据运算 
DataFrame对象的数据运算方法如表5-1 所示,表格中的df表示一个DataFrame 
对象。
表5-1 DataFrame对象的数据运算方法
数据运算方法描 述
df*N df的所有元素乘以N 
df1+df2 将df1和df2的行名和列名都相同的元素相加,其他位置的元
素用NaN填充
df1.add(other,axis=c' olumns',level= 
None,fill_value=None) 
将df1中的元素与other中的元素相加,other的类型可以是
scalar(标量)、sequence(序列)、Series、DataFrame等形式
df1.sub(other,axis=c' olumns',level= 
None,fill_value=None) 将df1中的元素与other中的元素相减
df1.div(other,axis='columns',level= 
None,fill_value=None) 将df1中的元素与other中的元素相除
df1.mul(other,axis= 'columns',level 
=None,fill_value=None) 将df1中的元素与other中的元素相乘
1.df1+df2 
作用:将df1和df2的行名和列名都相同的元素相加,其他位置的元素用NaN 填充。 
>>>import pandas as pd 
>>>import numpy as np

78 
>>>df1=pd.DataFrame(np.arange(9).reshape((3,3)),columns=list('bcd'), index= 
['A','B','C']) 
>>>df2=pd.DataFrame(np.arange(12).reshape((4,3)),columns= list('bde'), index 
=['A','D','B','E']) 
>>>df1 
b c d 
A 0 1 2 
B 3 4 5 
C 6 7 8 
>>>df2 
b d e 
A 0 1 2 
D 3 4 5 
B 6 7 8 
E 9 10 11 
>>>df1+df2 #行名和列名都相同的元素相加,其他位置的元素用NaN 填充 
b c d e 
A 0.0 NaN 3.0 NaN 
B 9.0 NaN 12.0 NaN 
C NaN NaN NaN NaN 
D NaN NaN NaN NaN 
E NaN NaN NaN NaN 
2.df1.add(other,axis=c' olumns',level=None,fill_value=None) 
作用:若df1和other对象的行名和列名都相同的位置上的元素都存在时,直接将相应
的元素相加;同一行名和列名处,若其中一个对象在该处不存在元素,则先用fill_value指定
的值填充,然后相加;若同一行名和列名处,两个对象都不存在元素,则相加的结果用NaN 
填充。参
数说明如下。
other:取值集合{scalar(标量),sequence(序列),Series,DataFrame} 
axis:取值集合{'index' 或'columns'},axis=0 或'index' 表示按行比较,axis=1 
或c' olumns'表示按列比较。
level:int或name,选择不同的索引,一个DataFrame对象可能有两个索引。
fill_value:用于填充缺失值,默认将缺失值填充为NaN。 
>>>df1.add(10) #other 为标量10 
b c d 
A 10 11 12 
B 13 14 15 
C 16 17 18 
>>>df1.add([5,5,5]) #other 为列表 
b c d 
A 5 6 7 
B 8 9 10 
C 11 12 13 
>>>df1.add(df2) #与df1+df2 的计算结果一样

7 9 
b c d e 
A 0.0 NaN 3.0 NaN 
B 9.0 NaN 12.0 NaN 
C NaN NaN NaN NaN 
D NaN NaN NaN NaN 
E NaN NaN NaN NaN 
>>>df1.add(df2, fill_value=100) 
b c d e 
A 0.0 101.0 3.0 102.0 
B 9.0 104.0 12.0 108.0 
C 106.0 107.0 108.0 NaN 
D 103.0 NaN 104.0 105.0 
E 109.0 NaN 110.0 111.0 
5.1.2 数据排序
DataFrame对象的数据排序方法如表5-2 所示,表格中的df表示一个DataFrame 
对象。
表5-2 DataFrame对象的数据排序方法
数据排序方法描 述
df.sort_index(axis=0,ascending=True) 按行索引进行升序排序
df.sort_values(by,axis=0,ascending= 
True) 按指定的列或行进行值排序
df.rank(axis=0,method= 'average', 
ascending=True) 
沿着行计算元素值的排名,对于相同的两个元素值,沿着行
顺序排在前面的数据排名高,返回各个位置上元素值从小
到大排序对应的序号
1.df.sort_index(axis=0,ascending=True) 
作用:按行索引进行升序排序。
参数说明如下。
axis:axis=0,对行进行排序;axis=1,对列进行排序。
ascending:ascending=True,升序排序;ascending=False,降序排序。 
> >>df =pd.DataFrame({ 'col1' : ['A', 'A', 'B', 'D', 'C'],'col2' : [2, 9, 8, 7, 4], 
'col3': [1, 9, 4, 2, 3],}) 
>>>df 
col1 col2 col3 
0 A 2 1 
1 A 9 9 
2 B 8 4 
3 D 7 2 
4 C 4 3 
>>>df.sort_index(axis=1,ascending=False) #按列索引进行降序排列 
col3 col2 col1 
0 1 2 A

80 
1 9 9 A 
2 4 8 B 
3 2 7 D 
4 3 4 C 
2.df.sort_values(by,axis=0,ascending=True) 
作用:按指定的列或行进行值排序。
参数说明如下。
by:指定某些行或列作为排序的依据。
axis:axis=0,对行进行排序;axis=1,对列进行排序。 
>>>df.sort_values(by=['col1']) #按col1 进行排序 
col1 col2 col3 
0 A 2 1 
1 A 9 9 
2 B 8 4 
4 C 4 3 
3 D 7 2 
>>>df.sort_values(by=['col1','col2']) #按col1、col2 进行排序 
col1 col2 col3 
0 A 2 1 
1 A 9 9 
2 B 8 4 
4 C 4 3 
3 D 7 2 
3.df.rank(axis=0,method=a' verage',ascending=True) 
作用:沿着行计算元素值的排名,对于相同的两个元素值,沿着行顺序排在前面的数据
排名高,返回各个位置上元素值从小到大排序对应的序号。
参数说明如下。
axis:为0时沿着行,为1时沿着列。
method:method=a' verage'时,在相等分组中,为各个值分配平均排名;method= 'min' 
时,使用整个分组的最小排名;method='max'时,使用整个分组的最大排名;method= f'irst' 
时,按值在原始数据中的出现顺序分配排名。
ascending:boolean,默认值为True,True为升序排名,False为降序排名。 
>>>df =pd.DataFrame({'a':[4,2,3,2],'b':[15,21,10,13]},index= ['one','two', 
'three','four']) 
>>>df 
a b 
one 4 15 
two 2 21 
three 3 10 
four 2 13 
>>>df.rank(method ='first') #为每个位置分配从小到大排序后其元素对应的序号 
a b 
one 4.0 3.0 
two 1.0 4.0

8 1 
three 3.0 1.0 
four 2.0 2.0 
#将在两个2 这一分组的排名1 和2 的最大排名2 作为两个2 的排名
>>>df.rank(method ='max') 
a b 
one 4.0 3.0 
two 2.0 4.0 
three 3.0 1.0 
four 2.0 2.0 
#将两个2 这一分组的排名1 和2 的平均值1.5 作为两个2 的排名
>>>df.rank(method ='average') 
a b 
one 4.0 3.0 
two 1.5 4.0 
three 3.0 1.0 
four 1.5 2.0 
5.1.3 批量操作
DataFrame对象的apply()方法可对一行或一列做出操作,是对元素集合级别的操作, 
这里元素集合指的是以列为单位,或者以行为单位。
1.df.apply(func,axis=0) 
作用:对df的行或列应用函数func。
参数说明如下。
func:函数名称,指定应用在每行或每列的函数的名称。
axis:axis=0,对每一列应用func函数;axis=1,对每一行应用func函数。 
>>>import numpy as np 
>>>df=pd.DataFrame(np.arange(16).reshape((4,4)),columns=list('abcd'), 
index=['A','B','C','D']) 
>>>df 
a b c d 
A 0 1 2 3 
B 4 5 6 7 
C 8 9 10 11 
D 12 13 14 15 
>>>def f(x): #计算数组元素的取值间隔
return x.max()-x.min() 
>>>df.apply(f,axis=0) #求每一列元素的取值间隔
a 12 
b 12 
c 12 
d 12 
dtype: int64 
>>>df.apply(f,axis=1) 
A 3 
B 3 
C 3

82 
D 3 
dtype: int64 
apply()函数可一次执行多个函数,作用于行或列时,一次返回多个结果。 
>>>def f1(x): 
return pd.Series([x.max(),x.min()],index=['max','min']) 
>>>df.apply(f1,axis=0) #操作列 
a b c d 
max 12 13 14 15 
min 0 1 2 3 
>>>df.apply(np.sum, axis=1) #操作行
A 6 
B 22 
C 38 
D 54 
>>>df.apply(np.square) #操作元素 
a b c d 
A 0 1 4 9 
B 16 25 36 49 
C 64 81 100 121 
D 144 169 196 225 
>>>df['a'].apply(lambda x: 111 if x<8 else 0) #Lambda 函数
A 111 
B 111 
C 0 
D 0 
2.df.applymap(func) 
作用:将func函数应用到各个元素上。 
>>>df 
a b c d 
A 0 1 2 3 
B 4 5 6 7 
C 8 9 10 11 
D 12 13 14 15 
>>>def f2(x): 
return 2*x+1 
>>>df.applymap(f2) 
a b c d 
A 1 3 5 7 
B 9 11 13 15 
C 17 19 21 23 
D 25 27 29 31 
5.2 数据集成
5.2.1 两个DataFrame对象的连接 
DataFrame对象的merge()方法用于连接两个DataFrame对象,语法格式如下。

8 3 
df1.merge(df2, how='inner', on=None, left_on=None, right_on=None, left_index= 
False, right_index=False, sort=False, suffixes=('_x', '_y')) 
作用:通过行索引或列索引进行两个DataFrame对象的连接。
参数说明如下。
df2:拟被合并的DataFrame对象。
how:{l'eft',r'ight',o' uter',i'nner'},连接的方式。how=left表示以左边df1的键为基
准,右边出现匹配失败的用NaN 代替;how=right表示以右边df2的键为基准;how=outer 
表示以左右两边DataFrame共有的键为基准,匹配成功的保留,匹配失败的键值对以NaN 
进行替换;how=inner表示以左右两边DataFrame共有的键为基准,匹配成功的保留,匹配
失败所在的行全部删除,how默认值为inner。
on:设置连接的共有列名,默认为None,以最多相同的共有列名作连接键。
left_on=None和right_on=None:以上on是在两个df有相同的列名的情况下使用, 
如果两个df没有相同的列名,使用left_on和right_on分别指明左边和右边的连接列名。
left_index和right_index:默认都为False,如果需要按行索引进行合并,则需要使用
left_index和right_index指明以index为键,on、left_on、right_on都是指定以列为连接键。
如果使用了left_index或者right_index,必须指明另一方的参考键。如果是left_on ='**' 
和right_index= True或者left_index=True和right_on= *' *',index取on所在的一方, 
如果是left_index=True和right_index= True,取两者相同的。
sort=False:合并结果是否按on指定的键进行排序。
suffixes:合并后如果有重复列,分别加上什么后缀,默认加上后缀_x、_y进行区别。
1.不同的合并方式 
>>>df1 =pd.DataFrame({'a':['a1','a2','a3'], 'b':['b1','b2','b3'], 'key1':['a', 
'b','c'], 'key2':['d','e','f']}) 
>>>df2 =pd.DataFrame({'c':['c1','c2','c3'], 'd':['d1','d2','d3'], 'key1':['a', 
'b','a'], 'key2':['d','e','g']}) 
>>>print(df1) 
a b key1 key2 
0 a1 b1 a d 
1 a2 b2 b e 
2 a3 b3 c f 
>>>print(df2) 
c d key1 key2 
0 c1 d1 a d 
1 c2 d2 b e 
2 c3 d3 a g 
>>>df1.merge(df2,how ="left", on =['key1','key2']) #how =left,以左边键为基准 
a b key1 key2 c d 
0 a1 b1 a d c1 d1 
1 a2 b2 b e c2 d2 
2 a3 b3 c f NaN NaN 
>>>df1.merge(df2,how ="right", on =['key1','key2']) #how =right,以右边键为基准

84 
a b key1 key2 c d 
0 a1 b1 a d c1 d1 
1 a2 b2 b e c2 d2 
2 NaN NaN a g c3 d3 
>>>df1.merge(df2,how ="inner", on =['key1','key2']) #how =inner,取左右交集 
a b key1 key2 c d 
0 a1 b1 a d c1 d1 
1 a2 b2 b e c2 d2 
"outer"与"inner"用法对应,以左右两边DataFrame共有的键为基准,匹配成功的保
留,匹配失败的键对应的值以NaN 进行替换。 
>>>df1.merge(df2,how ="outer", on =['key1','key2']) #how =outer,左右两边并集 
a b key1 key2 c d 
0 a1 b1 a d c1 d1 
1 a2 b2 b e c2 d2 
2 a3 b3 c f NaN NaN 
3 NaN NaN a g c3 d3 
2.具有不同列名的合并 
>>>df3 =pd.DataFrame({'lkey': ['Zhang', 'Wang', 'Li', 'Zhao'], 'value': [70, 80, 
85, 95]}) 
>>>df4 =pd.DataFrame({'rkey': ['Zhang', 'Wang', 'Li', 'Zhao'], 'value': [7, 8, 
8.5, 9.5]}) 
>>>print(df3) 
lkey value 
0 Zhang 70 
1 Wang 80 
2 Li 85 
3 Zhao 95 
>>>print(df4) 
rkey value 
0 Zhang 7.0 
1 Wang 8.0 
2 Li 8.5 
3 Zhao 9.5 
>>>df3.merge(df4, left_on ='lkey',right_on ='rkey') 
lkey value_x rkey value_y 
0 Zhang 70 Zhang 7.0 
1 Wang 80 Wang 8.0 
2 Li 85 Li 8.5 
3 Zhao 95 Zhao 9.5 
#设置suffixes 参数
>>>df3.merge(df4, left_on ='lkey',right_on ='rkey',suffixes=("_lf","_rf")) 
lkey value_lf rkey value_rf 
0 Zhang 70 Zhang 7.0 
1 Wang 80 Wang 8.0 
2 Li 85 Li 8.5 
3 Zhao 95 Zhao 9.5

8 5 
3.指定是否按索引进行合并 
>>>df5 = pd.DataFrame({'key1':['a','b','c','d'],'key2':['e','f','g','h']}, 
index=['k','l','m','n']) 
>>>df6 =pd.DataFrame({'key1':['k',6,'l']},index=['a','m','c']) 
>>>print(df5) 
key1 key2 
k a e 
l b f 
m c g 
n d h 
>>>print(df6) 
key1 
a k 
m 6 
c l 
>>>df5.merge(df6, left_index=True, right_index=True) #根据行索引进行合并 
key1_x key2 key1_y 
m c g 6 
>>>df5.merge(df6,left_on='key1', right_index=True) 
key1 key1_x key2 key1_y 
k a a e k 
m c c g l 
5.2.2 多个DataFrame对象的堆叠
pandas的concat()函数可一次实现对多个DataFrame对象的堆叠,默认是对所有列在
垂直方向进行堆叠,index为原来各自的索引。 
pandas.concat(objs, axis=0, join='outer', ignore_index=False, keys=None, sort=None) 
作用:以指定的轴将多个对象堆叠到一起,concat()不会去掉重复的记录。
参数说明如下。
objs:需要连接的对象集合,其类型可以是Series、DataFrame、列表或字典。
axis:连接方向,axis=0,对行操作,纵向连接;axis=1,对列操作,横向连接。
join:表示堆叠方式,只有outer和inner方式,默认为outer,inner表示只对相同列进
行堆叠。
keys:创建层次化索引,以标识数据来自不同的连接对象。
ignore_index:ignore_index=False,保留原索引;ignore_index=True,忽略原索引,重
建索引。
1.join指定堆叠方式 
>>>s1 =pd.DataFrame([[1,2,3],[4,5,6]],columns=['a','b','c']) 
>>>s2 =pd.DataFrame([[3,4,'w'],[5,6,'x']],columns=['a','b','d']) 
>>>print(s1) 
a b c 
0 1 2 3 
1 4 5 6

86 
>>>print(s2) 
a b d 
0 3 4 w 
1 5 6 x 
#join 为'inner'时得到的是两表的交集,是'outer'时得到的是两表的并集
>>>print(pd.concat([s1,s2])) 
a b c d 
0 1 2 3.0 NaN 
1 4 5 6.0 NaN 
0 3 4 NaN w 
1 5 6 NaN x 
>>>print(pd.concat([s1,s2],join="inner")) 
a b 
0 1 2 
1 4 5 
0 3 4 
1 5 6 
2.在水平方向进行堆叠
如果是在水平方向进行堆叠,需要指定axis=1,如果合并后有相同列名称,可通过add 
_prefix或者add_suffix为其中一个添加名称前缀或后缀。 
>>>print(pd.concat([s1,s2],axis=1,sort=False)) 
a b c a b d 
0 1 2 3 3 4 w 
1 4 5 6 5 6 x 
3.ignore_index指定是否保留原对象的index 
ignore_index=False,保留原索引;ignore_index=True,忽略原索引,重建索引。 
>>>print(pd.concat([s1,s2],ignore_index=True)) 
a b c d 
0 1 2 3.0 NaN 
1 4 5 6.0 NaN 
2 3 4 NaN w 
3 5 6 NaN x 
4.参数key用于创建层次索引以标识数据源自于哪张表 
>>>pd.concat([s1,s2],keys=['s1','s2']) 
a b c d 
s1 0 1 2 3.0 NaN 
1 4 5 6.0 NaN 
s2 0 3 4 NaN w 
1 5 6 NaN x 
5.2.3 DataFrame对象的行列旋转
1.列旋转为行 
df.stack(level=-1, dropna=True)