3.2.3 数据拼接
当我们面对两份或者多份数据时,常常需要对它们进行一些拼接、合并操作来整合我们想要的数据。Pandas提供了merge、join、concat等多种方法来帮助我们快速完成这些数据拼接任务。
1.merge方法
Pandas的merge方法是基于共同的列将两个数据表连接起来。如果你熟悉关系型数据库,那么你会发现merge方法和关系型数据库中的join其实是一致的。merge方法的主要参数说明如表3-5所示。
表3-5 merge方法的主要参数
下面介绍merge方法中how参数指定的四种连接的含义及具体实现。
1)how=‘inner’表示内连接,即基于两个表的共同列取交集,如图3-2所示。
图3-2 内连接
假设存在如下两张表,分别为left_df和right_df。
In [65]: left_df Out[65]: ID Name 0 1 A 1 2 B 2 3 C 3 4 D 4 5 E In [66]: right_df Out[66]: Age ID 0 18 1 1 19 2 2 16 3 3 50 5 4 20 6
可以通过指定共同列ID进行内连接,得到结果df1。
In [67]: df1 = pd.merge(left_df,right_df,how = 'inner',on = 'ID') In [68]: df1 Out[68]: ID Name Age 0 1 A 18 1 2 B 19 2 3 C 16 3 5 E 50
可以发现,原来的left_df和right_df表中各有5行数据,而内连接结果df1中只有4行数据,并且df1的ID列中只有1、2、3、5四个值,这刚好是left_df中ID列和right_df中ID列同时包含的值。而left_df的ID列中的4和right_df的ID列中的6均为单独存在,所以没有在内连接的结果中出现。
2)how=‘left’表示左连接,即基于左表的列进行连接,返回左表的全部行和右表满足ON条件的行,得到结果df2。如果左表的行在右表中没有匹配,那么这一行右表中的对应数据用NaN代替。左连接的示意图如图3-3所示。
图3-3 左连接
代码如下:
In [69]: df2 = pd.merge(left_df,right_df,how = 'left',on = 'ID') In [70]: df2 Out[70]: ID Name Age 0 1 A 18.0 1 2 B 19.0 2 3 C 16.0 3 4 D NaN 4 5 E 50.0
在左连接的结果df2中,ID列返回left_df中的所有ID值,不包括出现在right_df中而没有出现在left_df中的其他值,比如6。而在right_df中没有出现的ID值是4,所以左连接结果中ID=4的Age列的值为NaN。
3)how=‘right’表示右连接,与左连接刚好相反,它是基于右表的列进行连接的,返回右表的全部行和左表满足ON条件的行,得到结果df3。如果右表的行在左表中没有匹配,那么这一行左表中的对应数据用NaN代替。右连接的示意图如图3-4所示。
图3-4 右连接
代码如下:
In [71]: df3 = pd.merge(left_df,right_df,how = 'right',on = 'ID') In [72]: df3 Out[72]: ID Name Age 0 1 A 18 1 2 B 19 2 3 C 16 3 5 E 50 4 6 NaN 20
在右连接的结果df3中,ID列返回right_df中的所有ID值,不包括出现在left_df中而没有出现在right_df中的其他值,比如4。而在left_df中没有出现的ID值是6,所以结果df3中ID=6的Name列的值为NaN。
4)how=‘outer’表示外连接,其结果会返回左表和右表所有的行,对应结果df4。如果其中一个表数据的行在另一个表中没有匹配到,那么没有匹配到的数据就用NaN代替。外连接的示意图如图3-5所示。
图3-5 外连接
代码如下:
In [73]: df4 = pd.merge(left_df,right_df,how = 'outer',on = 'ID') In [74]: df4 Out[74]: ID Name Age 0 1 A 18.0 1 2 B 19.0 2 3 C 16.0 3 4 D NaN 4 5 E 50.0 5 6 NaN 20.0
在外连接的结果df4中,ID列返回right_df和left_df中的所有ID值。例如,在left_df中没有出现的值6,在df4中ID=6的Name列的值为NaN;在right_df中没有出现的值4,在df4中ID=4的Age列的值为NaN。
如果是基于多列的连接,将所有列名组成列表形式传给on参数即可:
In [75]: left_df2 = pd.DataFrame({"ID":[1,2,3,4,5], ...: "No":[100,101,102,103,104], ...: "Name":['A',"B","C","D","E"]}) In [76]: right_df2 = pd.DataFrame({"ID":[1,2,3,5,6], ...: "No":[100,101,102,103,105], ...: "Age":[18,19,16,50,20]}) In [77]: df5=pd.merge(left_df2,right_df2,how = 'left',on = ['ID','No']) In [78]: df5 Out[78]: ID Name No Age 0 1 A 100 18.0 1 2 B 101 19.0 2 3 C 102 16.0 3 4 D 103 NaN 4 5 E 104 NaN
关于merge方法中的其他参数,感兴趣的读者可以自行尝试。
2.join方法
join方法主要基于两个DataFrame的索引进行合并。join方法和merge方法类似,同样也可以实现四种连接方式,但join方法是基于索引进行连接,而merge方法既可以基于列连接也可以基于索引拼接。当然我们还可以通过将列设置成索引再使用join方法连接。但在一般情况下,我们都是直接采用merge方法连接。
这里是使用join方法进行左连接的简单示例。
In [79]: left_df.join(right_df,lsuffix="_left",rsuffix="_right") Out[79]: ID_left Name Age ID_right 0 1 A 18 1 1 2 B 19 2 2 3 C 16 3 3 4 D 50 5 4 5 E 20 6
其他连接方式与merge方法类似,这里不再赘述。
3.concat方法
concat方法主要是对Series或DataFrame进行行拼接或列拼接。concat方法中的主要参数及其说明如表3-6所示。
表3-6 concat方法中的参数
(1)行拼接
将多张具有相同字段的表进行拼接,比如将一年中四个季度各类广告投放产品的消耗情况表进行行拼接,形成年度消耗情况表,如果某张表中不存在该字段,则拼接后该字段的值为NaN。
In [80]: df1 = pd.DataFrame({'A': [100,102,50,580], 'B': [2,5,6,8]}) In [81]: df2 = pd.DataFrame({'A': [20,30,30,60],'C': [1,2,3,5]}) In [82]: pd.concat([df1,df2]) Out[82]: A B C 0 100 2.0 NaN 1 102 5.0 NaN 2 50 6.0 NaN 3 580 8.0 NaN 0 20 NaN 1.0 1 30 NaN 2.0 2 30 NaN 3.0 3 60 NaN 5.0
(2)列拼接
要实现列拼接,只要修改axis=1即可,作用与merge方法、join方法一样,不过concat方法不支持左连接和右连接。
In [83]: pd.concat([left_df,right_df],axis=1) Out[83]: ID Name Age ID 0 1 A 18 1 1 2 B 19 2 2 3 C 16 3 3 4 D 50 5 4 5 E 20 6