使用部分匹配消除pandas数据帧行

时间:2015-10-21 20:57:08

标签: python pandas merge

我想比较两个pandas数据帧,并通过比较A列和B列中的值来找出仅在df1中的行。我觉得我可以通过使用merge以某种方式执行此操作但无法弄清楚..

import pandas as pd

df1 = pd.DataFrame([[1,11, 111], [2,22, 222], [3, 33, 333]], columns=['A', 'B', 'C'])
df2 = pd.DataFrame([[1, 11]], columns=['A', 'B'])

DF1

    A   B   C
0   1   11  111
1   2   22  222
2   3   33  333

DF2

    A   B
0   1   11

Dataframe我想看

    A   B   C
1   2   22  222
2   3   33  333

3 个答案:

答案 0 :(得分:1)

基于this approach

import pandas as pd

df1 = pd.DataFrame([[1,11, 111], [2,22, 222], [3, 33, 333]], columns=['A', 'B', 'C'])
df2 = pd.DataFrame([[1, 11]], columns=['A', 'B'])

连接数据帧:

df = pd.concat([df1, df2])
df.reset_index(drop=True)

按您所需的比较列分组 - 在您的情况下,AB

df_gpby = df.groupby(['A','B'])

获取仅包含一个值的组的索引 - 即唯一AB对:

idx = [x[0] for x in df_gpby.groups.values() if len(x) == 1]

通过索引子集连接的数据框:

df.iloc[idx]

结果:

    A   B   C
1   2   22  222
2   3   33  333

答案 1 :(得分:1)

虽然vmg的解决方案很简洁,但它需要您知道需要分组的列。更通用的方法是:

首先从另一个数据框中减去一个数据框:

In [46]: df3 = df1.subtract(df2)

In [47]: df3
Out[47]: 
    A   B   C
0   0   0 NaN
1 NaN NaN NaN
2 NaN NaN NaN

你看到有趣的行是那些在df2中不存在的行,所以它们都是NaN。使用numpy方法,您可以找到这些行:

In [50]: np.isnan(df3.iloc[0])
Out[50]: 
A    False
B    False
C     True
Name: 0, dtype: bool

In [51]: np.isnan(df3.iloc[1])
Out[51]: 
A    True
B    True
C    True
Name: 1, dtype: bool

现在,你知道如何找到这些行,你可以做一个疯狂的一行:

In [52]: df1.iloc[[idx for idx, row in df3.iterrows() if 
                  all(np.isnan(df3.iloc[idx]))]]
Out[52]: 
   A   B    C
1  2  22  222
2  3  33  333

更新,让我们添加一个通用函数

def substract_dataframe(df1, df2):
    for i in [df1, df2]:
        if not isinstance(i, pd.DataFrame):
            raise ValueError(("Wrong argument given! 
                             All arguments must be DataFrame instances"))
    df = df1.subtract(df2)
    return df1.iloc[[idx for idx, row in df.iterrows() if      
                    all(np.isnan(df.iloc[idx]))]]

测试......

In [54]: substract_dataframe(df1, df2)
Out[54]: 
   A   B    C
1  2  22  222
2  3  33  333

In [55]: substract_dataframe(df1, 'sdf')
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-55-6ce801e88ce4> in <module>()
----> 1 substract_dataframe(df1, 'sdf')

<ipython-input-53-e5d7db966311> in substract_dataframe(df1, df2)
      2     for i in [df1, df2]:
      3         if not isinstance(i, pd.DataFrame):
----> 4             raise ValueError("Wrong argument given! All arguments must be DataFrame instances")
      5     df = df1.subtract(df2)
      6     return df1.iloc[[idx for idx, row in df.iterrows() if all(np.isnan(df.iloc[idx]))]]

ValueError: Wrong argument given! All arguments must be DataFrame instances

答案 2 :(得分:1)

merge

中添加indicator0.17.0一起使用
In [3544]: df1.merge(df2, how='left', indicator='_b').query('_b != "both"').drop('_b', 1)
Out[3544]:
   A   B    C
1  2  22  222
2  3  33  333

详细

In [3545]: df1.merge(df2, how='left', indicator='_b')
Out[3545]:
   A   B    C         _b
0  1  11  111       both
1  2  22  222  left_only
2  3  33  333  left_only

In [3546]: df1.merge(df2, how='left', indicator='_b').query('_b != "both"')
Out[3546]:
   A   B    C         _b
1  2  22  222  left_only
2  3  33  333  left_only