三、类连接操作

除了上述介绍的若干连接函数之外, pandas 中还设计了一些函数能够对两个表进行某些操作,这里把它们统称为类连接操作。

1. 比较

compare 是在 1.1.0 后引入的新函数,它能够比较两个表或者序列的不同处并将其汇总展示:

In [49]: df1 = pd.DataFrame({'Name':['San Zhang', 'Si Li', 'Wu Wang'],
   ....:                         'Age':[20, 21 ,21],
   ....:                         'Class':['one', 'two', 'three']})
   ....: 
In [50]: df2 = pd.DataFrame({'Name':['San Zhang', 'Li Si', 'Wu Wang'],
   ....:                         'Age':[20, 21 ,21],
   ....:                         'Class':['one', 'two', 'Three']})
   ....: 
In [51]: df1.compare(df2)
Out[51]: 
    Name         Class   
    self  other   self  other
1  Si Li  Li Si    NaN    NaN
2    NaN    NaN  three  Three

结果中返回了不同值所在的行列,如果相同则会被填充为缺失值 NaN ,其中 otherself 分别指代传入的参数表和被调用的表自身。

如果想要完整显示表中所有元素的比较情况,可以设置 keep_shape=True

In [52]: df1.compare(df2, keep_shape=True)
Out[52]: 
    Name         Age        Class   
    self  other self other   self  other
0    NaN    NaN  NaN   NaN    NaN    NaN
1  Si Li  Li Si  NaN   NaN    NaN    NaN
2    NaN    NaN  NaN   NaN  three  Three

2. 组合

combine 函数能够让两张表按照一定的规则进行组合,在进行规则比较时会自动进行列索引的对齐。对于传入的函数而言,每一次操作中输入的参数是来自两个表的同名 Series ,依次传入的列是两个表列名的并集,例如下面这个例子会依次传入 A,B,C,D 四组序列,每组为左右表的两个序列。同时,进行 A 列比较的时候, s2 指代的就是一个全空的序列,因为它在被调用的表中并不存在,并且来自第一个表的序列索引会被 reindex 成两个索引的并集。具体的过程可以通过在传入的函数中插入适当的 print 方法查看。

下面的例子表示选出对应索引位置较小的元素:

In [53]: def choose_min(s1, s2):
   ....:     s2 = s2.reindex_like(s1)
   ....:     res = s1.where(s1<s2, s2)
   ....:     res = res.mask(s1.isna()) # isna表示是否为缺失值,返回布尔序列
   ....:     return res
   ....: 
In [54]: df1 = pd.DataFrame({'A':[1,2], 'B':[3,4], 'C':[5,6]})
In [55]: df2 = pd.DataFrame({'B':[5,6], 'C':[7,8], 'D':[9,10]}, index=[1,2])
In [56]: df1.combine(df2, choose_min)
Out[56]: 
    A    B    C   D
0 NaN  NaN  NaN NaN
1 NaN  4.0  6.0 NaN
2 NaN  NaN  NaN NaN

练一练

请在上述代码的基础上修改,保留 df2 中4个未被 df1 替换的相应位置原始值。

此外,设置 overtwrite 参数为 False 可以保留 被调用表 中未出现在传入的参数表中的列,而不会设置未缺失值:

In [57]: df1.combine(df2, choose_min, overwrite=False)
Out[57]: 
     A    B    C   D
0  1.0  NaN  NaN NaN
1  2.0  4.0  6.0 NaN
2  NaN  NaN  NaN NaN

练一练

除了 combine 之外, pandas 中还有一个 combine_first 方法,其功能是在对两张表组合时,若第二张表中的值在第一张表中对应索引位置的值不是缺失状态,那么就使用第一张表的值填充。下面给出一个例子,请用 combine 函数完成相同的功能。

In [58]: df1 = pd.DataFrame({'A':[1,2], 'B':[3,np.nan]})
In [59]: df2 = pd.DataFrame({'A':[5,6], 'B':[7,8]}, index=[1,2])
In [60]: df1.combine_first(df2)
Out[60]: 
     A    B
0  1.0  3.0
1  2.0  7.0
2  6.0  8.0