【问题标题】:Eliminate pandas dataframe rows with partial matches消除部分匹配的 pandas 数据帧行
【发布时间】:2016-01-21 00:39:22
【问题描述】:

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

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

我想看的数据框

    A   B   C
1   2   22  222
2   3   33  333

【问题讨论】:

  • 在您展示的示例中,您似乎想要消除部分匹配的行。对吗?
  • 是的,完全正确

标签: python pandas merge


【解决方案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)

按您想要的比较列分组 - 在您的情况下,A 和 B:

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

获取只有一个值的组的索引 - 即唯一的 A,B 对:

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

【讨论】:

    【解决方案2】:

    虽然 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
    

    【讨论】:

      【解决方案3】:

      在indicator 中使用merge,在0.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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-04-28
        • 2018-04-18
        • 1970-01-01
        • 2017-12-27
        • 1970-01-01
        • 2020-02-13
        • 2021-10-16
        • 2021-01-29
        相关资源
        最近更新 更多