【问题标题】:How to drop duplicates from one data frame if found in another dataframe如果在另一个数据框中找到重复项,如何从一个数据框中删除重复项
【发布时间】:2018-08-01 09:47:22
【问题描述】:

我有两个数据框,每个都有数百列。

#df1 = 190 columns
#df2 = 262 columns

#subset dataframe
df1 = pd.DataFrame({'Key': ['10003', '10009', '10010', '10034', '10665'], 
               'Num1': [12,13,13,13,13],
               'Color': ['red','orange','red','red','red'],
              'Date1': [20120506, 20120506, 20120506,20120506,20120620],
              'Date2': [20120528, 20120507, 20120615,20120629,20120621]})
df2 = pd.DataFrame({'Key': ['10003', '10009', '10010', '10011', '10012','10034','10034', '10034'], 
               'Num1': [12,13,13,13,13,13,14,14],
               'Num2': [121,122,122,124,125,126,127,128],
              'Date1': [20120506, 20120506, 20120506,20120506,20120620,20120506,20120206,20120405],
              'Date2': [20120528, 20120507, 20120615,20120629,20120621,20120629,20120506,20120506]})

我想删除 df2 中也在 df1 中的所有行,但保持 df1 不变。

我在使用 pd.concat() 或 merge() 时非常接近,但问题是我正在创建一堆不必要的列 [使用 concat() 和 merge()] 并且添加了仅在 df1 中找到的行到 df2 [使用 concat()]。实际上,当 'Key'、'Date1'、'Num' 和 'Date2' 在行中常见时,它们可以被视为重复。

下面的尝试很接近,但它从 df1 添加了额外的列,并保留了 df1 中的所有额外行。我不想要 df1 中的任何其他列或行,只是为了删除两个 dfs 中存在的 df2 中的任何重复项。 df1 将保持不变。

a = pd.concat([df2,df1])
a.drop_duplicates(subset=['Key', 'Num1','Date1','Date2'],keep=False, inplace=True)

    Color   Date1       Date2       Key     Num1    Num2
3   NaN     20120506    20120629    10011   13      124.0
4   NaN     20120620    20120621    10012   13      125.0
6   NaN     20120206    20120506    10034   14      127.0
7   NaN     20120405    20120506    10034   14      128.0
4   red     20120620    20120621    10665   13      NaN

根据here 的建议,我也尝试了合并,但我仍然得到重复的列。

df_all = df2.merge(df1.drop_duplicates(), on=['Key', 'Num1','Date1','Date2'], 
               how='left', indicator=True)
df_all[df_all['_merge'] == 'left_only']

合并结果,

     Date1      Date2       Key     Num1    Num2    Color   _merge
3    20120506   20120629    10011   13      124     NaN     left_only
4    20120620   20120621    10012   13      125     NaN     left_only
6    20120206   20120506    10034   14      127     NaN     left_only
7    20120405   20120506    10034   14      128     NaN     left_only

合并让我得到了正确的行,但得到了额外的列。通常这不会是一个问题,我可以 .drop() 但合并后有 100 多个额外的列。

如何在不增加列或从 df1.xml 添加其他行的情况下删除重复项。

最终预期结果:

    Date1       Date2       Key     Num1    Num2
3   20120506    20120629    10011   13      124.0
4   20120620    20120621    10012   13      125.0
6   20120206    20120506    10034   14      127.0
7   20120405    20120506    10034   14      128.0

【问题讨论】:

    标签: python pandas dataframe merge concat


    【解决方案1】:

    使用on 键作为df1 的子集

    In [514]: on = ['Date1', 'Date2', 'Num1', 'Key']
    
    In [515]: (df2.merge(df1[on], on=on, how='left', indicator=True)
                  .query('_merge == "left_only"').drop('_merge', 1))
    Out[515]:
          Date1     Date2    Key  Num1  Num2
    3  20120506  20120629  10011    13   124
    4  20120620  20120621  10012    13   125
    6  20120206  20120506  10034    14   127
    7  20120405  20120506  10034    14   128
    

    【讨论】:

    • 现在 Pandas v1.3.3 对 .drop('_merge', 1) 有弃用警告。与关键字参数一起使用:.drop(columns='_merge')
    【解决方案2】:

    您可以将concatkeys 一起使用

    s=pd.concat([df1,df2],keys=[1,2]).drop_duplicates(['Key', 'Num1','Date1','Date2'],keep='first')
    
    
    df1=s.loc[1].dropna(axis=1)
    df1
    Out[1260]: 
        Color     Date1     Date2    Key  Num1
    0     red  20120506  20120528  10003    12
    1  orange  20120506  20120507  10009    13
    2     red  20120506  20120615  10010    13
    3     red  20120506  20120629  10034    13
    4     red  20120620  20120621  10665    13
    df2=s.loc[2].dropna(axis=1)
    df2
    Out[1262]: 
          Date1     Date2    Key  Num1   Num2
    3  20120506  20120629  10011    13  124.0
    4  20120620  20120621  10012    13  125.0
    6  20120206  20120506  10034    14  127.0
    7  20120405  20120506  10034    14  128.0
    

    【讨论】:

      【解决方案3】:

      这是一种方式。只需在相反的方向连接,然后删除重复项。最后从df1 中删除不需要的行/列。

      df = pd.concat([df1, df2], ignore_index=True)\
             .drop_duplicates(subset=['Date1', 'Date2', 'Key', 'Num1'], keep=False)
      
      df = df.drop(df1.index & df.index, 0)\
             .drop(set(df1.columns) - set(df2.columns), 1)
      
      #        Date1     Date2    Key  Num1   Num2
      # 8   20120506  20120629  10011    13  124.0
      # 9   20120620  20120621  10012    13  125.0
      # 11  20120206  20120506  10034    14  127.0
      # 12  20120405  20120506  10034    14  128.0
      

      这与@Wen's solution 非常相似,主要区别在于删除不需要的df1 数据是明确的。但是请注意,此方法会重置索引。

      【讨论】:

        猜你喜欢
        • 2019-03-14
        • 1970-01-01
        • 1970-01-01
        • 2021-04-27
        • 2020-03-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多