【问题标题】:Remove one dataframe from another with Pandas使用 Pandas 从另一个数据帧中删除一个数据帧
【发布时间】:2017-11-16 16:24:06
【问题描述】:

我有两个不同大小的数据框 (df1 nad df2)。我想从df1 中删除存储在df2 中的所有行。

所以如果我有df2 等于:

     A  B
0  wer  6
1  tyu  7

df1 等于:

     A  B  C
0  qwe  5  a
1  wer  6  s
2  wer  6  d
3  rty  9  f
4  tyu  7  g
5  tyu  7  h
6  tyu  7  j
7  iop  1  k

最终的结果应该是这样的:

     A  B  C
0  qwe  5  a
1  rty  9  f
2  iop  1  k

我能够通过使用 for 循环来实现我的目标,但我想知道是否有更好、更优雅、更高效的方式来执行此类操作。

这是我编写的代码,以备您需要时使用: 将熊猫导入为 pd

df1 = pd.DataFrame({'A' : ['qwe', 'wer', 'wer', 'rty', 'tyu', 'tyu', 'tyu', 'iop'],
                    'B' : [    5,     6,     6,     9,     7,     7,     7,     1],
                    'C' : ['a'  ,   's',   'd',   'f',   'g',   'h',   'j',   'k']})

df2 = pd.DataFrame({'A' : ['wer', 'tyu'],
                    'B' : [    6,     7]})

for i, row in df2.iterrows():
    df1 = df1[(df1['A']!=row['A']) & (df1['B']!=row['B'])].reset_index(drop=True)

【问题讨论】:

    标签: python pandas dataframe compare difference


    【解决方案1】:

    mergequery 的过滤器一起使用,最后通过drop 删除辅助列:

    df = pd.merge(df1, df2, on=['A','B'], how='outer', indicator=True)
           .query("_merge != 'both'")
           .drop('_merge', axis=1)
           .reset_index(drop=True)
    print (df)
         A  B  C
    0  qwe  5  a
    1  rty  9  f
    2  iop  1  k
    

    【讨论】:

    • 是否可以指定列名'A'和'B'?
    • 是的,当然,添加参数on
    • dekujiu moc kamarad!
    【解决方案2】:

    我发现的最简洁的方法是使用您要删除的数据框的索引从 pandas 中删除:

    df1.drop(df2.index, axis=0,inplace=True)
    

    【讨论】:

    • 我相信这并不能回答这个问题。它假定相同的行将具有相同的索引。但是,在问题中发布的示例中,情况并非如此。因此,您将从 df1 中删除索引为 0 和 1 的行。
    • 天才回答谢谢!甚至可以将其扩展到列名,例如:df.spec_col.drop(drop.index,axis = 0)
    【解决方案3】:

    您可以使用 np.in1d 检查 df1 中的任何行是否存在于 df2 中。然后将其用作反向掩码从 df1 中选择行。

    df1[~df1[['A','B']].apply(lambda x: np.in1d(x,df2).all(),axis=1)]\
                       .reset_index(drop=True)
    Out[115]: 
         A  B  C
    0  qwe  5  a
    1  rty  9  f
    2  iop  1  k
    

    【讨论】:

      【解决方案4】:

      pandas 有一个名为isin 的方法,但是这依赖于唯一索引。我们可以定义一个 lambda 函数,从现有的 'A'df1df2 中创建可以在其中使用的列。然后我们否定它(因为我们想要不在df2 中的值)并重置索引:

      import pandas as pd
      
      df1 = pd.DataFrame({'A' : ['qwe', 'wer', 'wer', 'rty', 'tyu', 'tyu', 'tyu', 'iop'],
                          'B' : [    5,     6,     6,     9,     7,     7,     7,     1],
                          'C' : ['a'  ,   's',   'd',   'f',   'g',   'h',   'j',   'k']})
      
      df2 = pd.DataFrame({'A' : ['wer', 'tyu'],
                          'B' : [    6,     7]})
      
      unique_ind = lambda df: df['A'].astype(str) + '_' + df['B'].astype(str)
      print df1[~unique_ind(df1).isin(unique_ind(df2))].reset_index(drop=True)
      

      印刷:

           A  B  C
      0  qwe  5  a
      1  rty  9  f
      2  iop  1  k
      

      【讨论】:

        【解决方案5】:

        我认为最干净的方法是:

        我们有基础数据框 D,并且想要删除子集 D1。设输出为 D2

        D2 = pd.DataFrame(D, index = set(D.index).difference(set(D1.index))).reset_index()
        

        【讨论】:

          【解决方案6】:

          我发现其他替代方法也很有用:

          pd.concat([df1,df2], axis=0, ignore_index=True).drop_duplicates(subset=["A","B"],keep=False, ignore_index=True)
          
          
                   A   B  C
              0   qwe  5  a
              1   rty  9  f
              2   iop  1  k
          

          keep=False 删除两个重复项。

          不需要在两个 df 之间放置所有相等的列,所以我觉得这更容易一些。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2021-08-28
            • 1970-01-01
            • 1970-01-01
            • 2018-03-09
            • 1970-01-01
            • 2015-09-08
            • 2018-07-29
            • 2021-04-26
            相关资源
            最近更新 更多