Python广告数据挖掘与分析实战
上QQ阅读APP看书,第一时间看更新

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