数据整合:聚合、合并、重塑
1.层次化索引(列和行都可以是层次化索引)
data = pd.Series(np.random.randn(9),
index=[['a', 'a', 'a', 'b', 'b', 'c', 'c', 'd', 'd'],
[1, 2, 3, 1, 3, 1, 2, 2, 3]])
data数据如下: (index第一个元素是外层索引,第二个元素是内层索引)
a 1 -0.204708
2 0.478943
3 -0.519439
b 1 -0.555730
3 1.965781
c 1 1.393406
2 0.092908
d 2 0.281746
3 0.769023
data.index.names = ['key1', 'key2']
data['b'] # 获取外层索引是b的行数据
data['b':'c'] # 获取外层索引从b到c的行数据(包括c)
data.loc[['b', 'd']] # 获取外层索引是b和d的行数据
data.loc[:, 2] # 获取内层索引是2的行数据
data.unstack() # 将内层索引变为列索引(缺失值用NaN填充)
data.unstack().stack() # unstack的逆运算是stack
2. 重排和分级排序
data.swaplevel('key1', 'key2') # 将key1和key2索引层次互换,不修改原数据生成新数据
data.swaplevel(0, 1).sort_index(level=0)
data.sum(level='key2') # 根据key2索引进行行求和统计
data.sum(level='color', axis=1) # 根据color索引进行列求和统计
frame2 = frame.set_index(['c', 'd']) # 将frame的c、d列作为索引(默认这两列不再是数据)
frame.set_index(['c', 'd'], drop=False) # 作为索引的同时,不删除,保留作为数据
frame2.reset_index() # 将层次化索引转移到列里面去作为数据
3. 合并数据集
pd.merge(df1, df2) # 默认是将df1和df2共有的列当做键来合并
pd.merge(df1, df2, on='key') # 指定用key列当做键合并
pd.merge(df3, df4, left_on='lkey', right_on='rkey') # 分别指定df3和df4列作为合并条件
默认情况下,merge是做的内连接inner,取交集(还有left/right/outer)
pd.merge(df1, df2, how='outer') # 传入how改为外连接,取并集
pd.merge(left, right, on='key1', suffixes=('_left', '_right')) # 有重复列名给列名加后缀区别(默认加_x,_y)
pd.merge(left1, right1, left_on='key', right_index=True) # 传入 right_index=True表示用索引作为连接键合并(left_index或者两个都传也行)
left2.join(right2, how='outer') # 默认用索引合并
left1.join(right1, on='key') # 指明用key作为合并键
left2.join([right2, another], how='outer') # 直接和dataframe合并(another是一个dataframe)
4.轴向连接
数据合并运算也被称作连接(concatenation)、绑定(binding)或堆叠(stacking)
arr = np.arange(12).reshape((3, 4)) # 3乘4的多维数组(ndarry类型)
np.concatenate([arr, arr], axis=1) # ndarry类型数据的合并(列数增加,行数不变,axis=1表示水平连接)
np.concatenate([a,a]) # ndarry类型垂直连接
pd.concat([s1, s2, s3]) # Series或者dataframe数据合并(默认行数增加,按列匹配拼接)
pd.concat([s1, s2, s3], axis=1) # 按行匹配,列数拼接增加(axis=1表示水平连接)
pd.concat([s1,s2],ignore_index = True) # 丢弃原有的索引,重新创建索引
pd.concat([s1, s4], axis=1, join='inner') # 传入join参数将默认的outer连接改为inner连接
result = pd.concat([s1, s1, s3], keys=['one','two', 'three']) # 为拼接的每一个数据集起一个外层索引名(axis=1时,keys表示给列取索引)
pd.concat([s1, s4], axis=1, join_axes=[['a', 'c', 'b', 'e']]) # join_axes设置另外一轴的索引
pd.concat([df1, df2], axis=1, keys=['level1', 'level2']) # 水平连接,给连接的两个数据集各取外层索引名level1和level2
pd.concat({'level1': df1, 'level2': df2}, axis=1) # 水平连接,通过传递字典给数据集取外层索引名
data = np.where(pd.isnull(a), b, a) # pandas三目运算:pd.isnull(a)真,那么返回b,否则返回a
data = df1.combine_first(df2) # 将df2的数据填充到df1中缺失数据(对应位填充),df2比df1数据量更多,那就添加到df1中,返回新的df1,原来的df1不会改变
5.数据重塑和轴向旋转
result = data.stack() # 将列转换为行(一般转为行内层索引),Series没有stack方法
result.unstack() # 将行转换为列
result.reindex(index=ilst('abcd')) # 重新定义行索引,返回一个新数据
result.reindex(columns=ilst('abcd')) # 重新定义列索引,返回一个新数据
data.pivot(index='userNum', columns='subjectCode', values='score') # 从data中重新组装数据,index为行索引,columns为列索引,values为填充数据,如果没定义values,则会将剩下未选中的所有列作为外层列索引重组数据
data.pivot_table('prop', index='year',columns='sex', aggfunc=sum) # 从data数据集中取prop列作为运算数据,index作为行索引,columns作为列索引,aggfunc作为计算方法,没有值的用NaN填充(默认可以修改),可以写成下面形式:
pd.pivot_table(data,values='prop', index='year',columns='sex', aggfunc=sum)
pivot()将长数据集转换成宽数据集,melt()则是将宽数据集变成长数据集
pd.melt(df, id_vars=['key'], value_vars=['A', 'B']) # 在df数据集中,id_vars指明的列保持不变,value_vars指明需要转换成variable列的值,对应生成value列的值:如下:
df 数据集:
A B C key
0 1 4 7 foo
1 2 5 8 bar
2 3 6 9 baz
data = pd.melt(df, id_vars=['key'], value_vars=['A', 'B'])
data数据集:
key variable value
0 foo A 1
1 bar A 2
2 baz A 3
3 foo B 4
4 bar B 5
5 baz B 6
如果不对id_vars或者value_vars做设置,默认会将其他所有列作为variable的值,这样只会有
三列,一列是默认的index行索引,一列是varable,一列是value
pd.melt(df) :
variable value
0 key foo
1 key bar
2 key baz
3 A 1
4 A 2
5 A 3
6 B 4
7 B 5
8 B 6
9 C 7
10 C 8
11 C 9
pd.melt(df, value_vars=['key', 'A', 'B'])
variable value
0 key foo
1 key bar
2 key baz
3 A 1
4 A 2
5 A 3
6 B 4
7 B 5
8 B 6