重复时,删除另一个数据框中的行

时间:2019-06-20 14:35:09

标签: python pandas dataframe

如果另一个数据框具有相同的行,我想删除一个数据框中的行。但是,我不想删除所有行,而只删除另一个数据框中的行数。请参考以下示例:

df1

   col1  col2
0     1    10
1     1    10
2     2    11
3     3    12
4     1    10

df2

   col1  col2
0     1    10
1     2    11
2     1    10
3     3    12
4     3    12

所需的输出:

df1

   col1  col2
      1    10

因为df1有3行1,10,而df2有2行1,10,所以您从每行中删除2,为df1保留1。如果df1中有4行,那么我想在df1中有两行1,10。与下面的df2相同:

df2

   col1  col2
      3    12

我的尝试

我可能正在考虑计算每个数据帧中有多少重复项,并通过减去df1来创建新的df2dupe_count,但想知道是否有更有效的方法。 / p>

df1g=df1.groupby(df1.columns.tolist(),as_index=False).size().reset_index().rename(columns={0:'dupe_count'})
df2g=df2.groupby(df2.columns.tolist(),as_index=False).size().reset_index().rename(columns={0:'dupe_count'})

2 个答案:

答案 0 :(得分:3)

这不是一个简单的问题,但是merge是您的朋友:

a, b = (df.assign(count=df.groupby([*df]).cumcount()) for df in (df1, df2))    
df1[a.merge(b, on=[*a], indicator=True, how='left').eval('_merge == "left_only"')]

   col1  col2
4     1    10

此处的想法是添加一个cumcount列以删除重复列(为每个列分配唯一的标识符)。然后,我们可以查看在随后的合并中哪些行不匹配。

a
   col1  col2  count
0     1    10      0
1     1    10      1
2     2    11      0
3     3    12      0
4     1    10      2

b
   col1  col2  count
0     1    10      0
1     2    11      0
2     1    10      1
3     3    12      0
4     3    12      1

a.merge(b, on=[*a], indicator=True, how='left')
   col1  col2  count     _merge
0     1    10      0       both
1     1    10      1       both
2     2    11      0       both
3     3    12      0       both
4     1    10      2  left_only

_.eval('_merge == "left_only"')
0    False
1    False
2    False
3    False
4     True
dtype: bool

如果您需要同时从df1df2获取不匹配的行,请使用外部合并:

out = a.merge(b, on=[*a], indicator=True, how='outer')
df1_filter = (
    out.query('_merge == "left_only"').drop(['count','_merge'], axis=1))
df2_filter = (
    out.query('_merge == "right_only"').drop(['count','_merge'], axis=1))

df1_filter
   col1  col2
4     1    10

df2_filter
   col1  col2
5     3    12

答案 1 :(得分:1)

这是使用repeat的另一种方法:

# count of the rows
c1 = df1.groupby(['col1', 'col2']).size()
c2 = df2.groupby(['col1', 'col2']).size()

# repeat the rows by values
(c1.repeat((c1-c2).clip(0))
   .reset_index()
   .drop(0, axis=1)
)
#   col1    col2
# 0 1   10

(c2.repeat((c2-c1).clip(0))
   .reset_index()
   .drop(0, axis=1)
)
#   col1    col2
# 0 3   12