在 df1 中删除也在 df2 中的行的可靠方法
Posted
技术标签:
【中文标题】在 df1 中删除也在 df2 中的行的可靠方法【英文标题】:Reliable way of dropping rows in df1 which are also in df2 【发布时间】:2020-02-27 23:23:15 【问题描述】:我有一个场景,我有一个 existing
数据框,我有一个 new
数据框,其中包含可能在 existing
框架中但也可能有新行的行。我一直在努力寻找一种可靠的方法,通过将 new
数据帧与 existing
数据帧进行比较来删除这些现有行。
我已经完成了我的作业。解决方案似乎是使用isin()
。但是,我发现这有隐患。特别是:
pandas get rows which are NOT in other dataframe
Pandas cannot compute isin with a duplicate axis
Pandas promotes int to float when filtering
有没有一种方法可以根据另一个数据帧中的成员资格/包含从一个数据帧中可靠地过滤掉行?下面显示了一个不捕获极端情况的简单用例。请注意,我想删除 existing
中的 new
中的行,以便 new
仅包含不在 existing
中的行。使用new
中的新行更新existing
的更简单问题可以通过pd.merge()
+ DataFrame.drop_duplicates()
实现
In [53]: df1 = pd.DataFrame(data = 'col1' : [1, 2, 3, 4, 5], 'col2' : [10, 11, 12, 13, 14])
...: df2 = pd.DataFrame(data = 'col1' : [1, 2, 3], 'col2' : [10, 11, 12])
In [54]: df1
Out[54]:
col1 col2
0 1 10
1 2 11
2 3 12
3 4 13
4 5 14
In [55]: df2
Out[55]:
col1 col2
0 1 10
1 2 11
2 3 12
In [56]: df1[~df1.isin(df2)]
Out[56]:
col1 col2
0 NaN NaN
1 NaN NaN
2 NaN NaN
3 4.0 13.0
4 5.0 14.0
In [57]: df1[~df1.isin(df2)].dropna()
Out[57]:
col1 col2
3 4.0 13.0
4 5.0 14.0
【问题讨论】:
Anti-Join Pandas的可能重复df1[~df1.isin(df2).all(1)]
?
@konvas 我不确定 - 我可以使用合并 + drop_duplicates()。但是,我需要一种方法来仅保留 new
中的新行 - 例如,我可能想要保留这些行。因此,它不仅仅是更新existing
- 它也是关于让new
只留下不在existing
中的新行
@anky_91 这和df1[~df1.isin(df2)].dropna()
有什么不同
对不起,如果我没有得到这个问题,如果你不想考虑行序列,下面的答案就是你想要的
【参考方案1】:
您可以尝试系列isin
。它独立于index
。即,它只检查值。您只需要将每个数据帧的列转换为一系列元组即可创建掩码
s1 = df1.agg(tuple, axis=1)
s2 = df2.agg(tuple, axis=1)
df1[~s1.isin(s2)]
Out[538]:
col1 col2
3 4 13
4 5 14
【讨论】:
这也很聪明:) +1【参考方案2】:我们可以使用DataFrame.merge
和indicator = True
+ DataFrame.query
和DataFrame.drop
df_filtered=( df1.merge(df2,how='outer',indicator=True)
.query("_merge == 'left_only'")
.drop('_merge',axis=1) )
print(df_filtered)
col1 col2
3 4 13
4 5 14
如果现在我们改变第 0 行的值:
df1.iat[0,0]=3
第 0 行不再被过滤
df_filtered=( df1.merge(df2,how='outer',indicator=True)
.query("_merge == 'left_only'")
.drop('_merge',axis=1) )
print(df_filtered)
col1 col2
0 3 10
3 4 13
4 5 14
一步一步
df_filtered=( df1.merge(df2,how='outer',indicator=True)
)
print(df_filtered)
col1 col2 _merge
0 3 10 left_only
1 2 11 both
2 3 12 both
3 4 13 left_only
4 5 14 left_only
5 1 10 right_only
df_filtered=( df1.merge(df2,how='outer',indicator=True).query("_merge == 'left_only'")
)
print(df_filtered)
col1 col2 _merge
0 3 10 left_only
3 4 13 left_only
4 5 14 left_only
df_filtered=( df1.merge(df2,how='outer',indicator=True)
.query("_merge == 'left_only'")
.drop('_merge',axis=1)
)
print(df_filtered)
col1 col2
0 3 10
3 4 13
4 5 14
【讨论】:
以上是关于在 df1 中删除也在 df2 中的行的可靠方法的主要内容,如果未能解决你的问题,请参考以下文章
Pyspark 基于另一个类似的数据框添加或删除数据框中的行