基于pandas DF的数据规整:清理,转化,合并,重塑。
大多时候存放在数据库中的原始表格数据不能满足某次数据处理的要求;或者你需要更改原始的数据表现形式,都需要进行数据的整理。
合并数据集(DF表格 merge, concat...)
- merge
pandas.merge:根据一个或多个不同的键将不同的DataFrame中的行连接起来(沿y轴续表)。
情形一
理解:pd.merge(df1,df2,on='key') # 多对一的情况默认参数how='inner'就是取两个表元素的交集: 以表2的单变量b为例,对应表一的三个变量,会产生新的三个变量b;它们会从表2取出表1中没有的字段,复制到表1上去;作为结果输出 。
df1 = pd.DataFrame({"key":['b','b','a','c','a','a','b'],'data1':range(7)})
df2 = pd.DataFrame({"key":['a','b','d'],'data2':range(3)})
df1 # 在指定列 key 变量名不唯一
Out[6]:
key data1
0 b 0
1 b 1
2 a 2
3 c 3
4 a 4
5 a 5
6 b 6
df2 # 在指定列 key上面 唯一变量名
Out[7]:
key data2
0 a 0
1 b 1
2 d 2
pd.merge(df1,df2)
Out[8]: # 合并的时候在默认以重叠的列名当作key
# 但最好用 参数 on="key" 显示指定
key data1 data2
0 b 0 1
1 b 1 1 # 最后的key 取 两个表 key变量 的交集;不进行去重
2 b 6 1
3 a 2 0
4 a 4 0
5 a 5 0
情形二:两个表的列名不同(注意仅仅是列名不同,列的变量名取值范围是一致的,只不过多少的问题,因为一般都是指定取交集,所以最好是一致的元素构成。)on= 这个参数就变成了 left_on= + right_on
df1 = pd.DataFrame({"lkey":['b','b','a','c','a','a','b'],'data1':range(7)})
df2 = pd.DataFrame({"rkey":['a','b','d'],'data2':range(3)})
#############################################################
df1
Out[12]:
lkey data1
0 b 0
1 b 1
2 a 2
3 c 3
4 a 4
5 a 5
6 b 6
df2
Out[13]:
rkey data2
0 a 0
1 b 1
2 d 2
pd.merge(df1,df2,left_on='lkey',right_on='rkey')
Out[11]:
lkey data1 rkey data2
0 b 0 b 1
1 b 1 b 1
2 b 6 b 1
3 a 2 a 0
4 a 4 a 0
5 a 5 a 0
- 谈谈how这个参数;在 merge操作当中,how="inner",how='outer',how='left',how='right'分别表示:交集,并集,交集+保留左边,交集+保留右边。
情形三:多对多的合并,做笛卡尔积(表1有2个b;表2有3个b;结果有 2x3 = 6个b)
df1 = pd.DataFrame({"key":['b','b','a','c','a','b'],'data1':range(6)})
df2 = pd.DataFrame({"key":['a','b','a','b','d'],'data2':range(5)})
##################################################################
df1
Out[18]:
key data1
0 b 0
1 b 1
2 a 2
3 c 3
4 a 4
5 b 5
df2
Out[19]:
key data2
0 a 0
1 b 1
2 a 2
3 b 3
4 d 4
pd.merge(df1,df2)
Out[20]:
key data1 data2
0 b 0 1
1 b 0 3
2 b 1 1
3 b 1 3
4 b 5 1
5 b 5 3
6 a 2 0
7 a 2 2
8 a 4 0
9 a 4 2
情形四:根据多个键合并;key=["key1", "key2"]
right=pd.DataFrame({'key1':['foo','foo','bar','bar'],'key2':["one",'one','one',"two"],"rval":[4,5,6,7]})
left=pd.DataFrame({'key1':['foo','foo','bar'],'key2':["one","two","one"],"lval":[1,2,3]})
#################################################################
left
Out[25]:
key1 key2 lval
0 foo one 1
1 foo two 2
2 bar one 3
right
Out[26]:
key1 key2 rval
0 foo one 4
1 foo one 5
2 bar one 6
3 bar two 7
pd.merge(left,right,on=["key1","key2"],how="outer")
Out[27]:
key1 key2 lval rval
0 foo one 1.0 4.0
1 foo one 1.0 5.0
2 foo two 2.0 NaN
3 bar one 3.0 6.0
4 bar two NaN 7.0
我的理解就是:现在的key1 key2 看成是一个 key;在如常做合并。
情形五:按索引合并 (重点)
传入:left_index=True
left1 = pd.DataFrame({'key':['a','b','a','a','b','c'],'value':range(6)})
right1 = pd.DataFrame({'group_val':[3.5,7]},index=['a','b'])
####################################################################
left1
Out[32]:
key value
0 a 0
1 b 1
2 a 2
3 a 3
4 b 4
5 c 5
right1
Out[33]:
group_val
a 3.5
b 7.0
pd.merge(left1,right1,left_on='key',right_index=True)
Out[34]:
key value group_val
0 a 0 3.5
2 a 2 3.5
3 a 3 3.5
1 b 1 7.0
4 b 4 7.0
还是遵循,在相同的变量下的笛卡尔积的原则,默认取交集:另外用索引作为key的时候,新生成的索引将用数字取代。
假设,两个表都取索引,意味着key变量名 不可能会有重复,这时候,在id 相同时,会增加 表2 的字段 给 表1 作为结果输出。
- concat
情形一:对于无重叠索引的多个 series结构(这里指的五重叠是series之间,series内部索引本不该重叠)
s1=pd.Series([0,1],index=['a','b'])
s2=pd.Series([2,3,4],index=['c','d','e'])
s3=pd.Series([5,6],index=['f','g'])
##################################################
s1
Out[42]:
a 0
b 1
dtype: int64
s2
Out[43]:
c 2
d 3
e 4
dtype: int64
s3
Out[44]:
f 5
g 6
dtype: int64
pd.concat([s1,s2,s3])
Out[45]:
a 0
b 1
c 2
d 3
e 4
f 5
g 6
dtype: int64
参数:axis=1 做横向合并(横向合并的时候,索引依此排开,列之间做并集)
pd.concat([s1,s2,s3],axis=1)
Out[46]:
0 1 2
a 0.0 NaN NaN
b 1.0 NaN NaN
c NaN 2.0 NaN
d NaN 3.0 NaN
e NaN 4.0 NaN
f NaN NaN 5.0
g NaN NaN 6.0
join_axes参数:
join_axes=[df1.index], 保留与df1的行标签一样的数据,配合axis=1一起用
join_axes=[df1.columns],保留与df1的列标签一样的数据,不要添加axis=1
df1 = pd.DataFrame({"key":['b','b','a','c','a','b'],'data1':range(6)})
df2 = pd.DataFrame({"key":['a','b','a','b','d'],'data2':range(5)})
##################################################################
df1
Out[53]:
key data1
0 b 0
1 b 1
2 a 2
3 c 3
4 a 4
5 b 5
df2
Out[54]:
key data2
0 a 0
1 b 1
2 a 2
3 b 3
4 d 4
pd.concat([df1,df2],axis=1) # 以二者的索引对齐,列标签直接叠加,哪怕是重复的也加
Out[55]:
key data1 key data2
0 b 0 a 0.0
1 b 1 b 1.0
2 a 2 a 2.0
3 c 3 b 3.0
4 a 4 d 4.0
5 b 5 NaN NaN
pd.concat([df1,df2],axis=1,join_axes=[df1.index])
Out[66]:
key data1 key data2
0 b 0 a 0.0
1 b 1 b 1.0
2 a 2 a 2.0
3 c 3 b 3.0
4 a 4 d 4.0
5 b 5 NaN NaN
pd.concat([df1,df2],axis=1,join_axes=[df2.index])
Out[67]:
key data1 key data2
0 b 0 a 0
1 b 1 b 1
- 参数 key 的作用(给合并的大表格中原来的三个分表格加一个索引,一边区分和快速查询分离)
附:concat函数全部参数
obj : 请以 [待合并的数据1,待合并的数据2,...]:注意:一定把数据用[ ]括起来。
axis: =0 表示纵向合并,=1表示横向合并
join=:表示合并的交并集
join_axes:
ingnore_index :不保留原索引