如果另一个数据框具有相同的行,我想删除一个数据框中的行。但是,我不想删除所有行,而只删除另一个数据框中的行数。请参考以下示例:
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
来创建新的df2
和dupe_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'})
答案 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
如果您需要同时从df1
和df2
获取不匹配的行,请使用外部合并:
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