给定两个数据帧A和B,它们都有列'x','y'我怎么能有效地删除A中的所有行,它们的对(x,y)出现在B中。
我考虑过在A上使用行迭代器实现它,然后每对检查它是否存在于B中,但我猜这是效率最低的方式......
我尝试使用Filter dataframe rows if value in column is in a set list of values中建议的.isin函数,但无法将其用于多列。
示例数据框:
A = pd.DataFrame([[1, 2], [1, 4], [3, 4], [2, 4]], columns=['x', 'y'])
B = pd.DataFrame([[1, 2], [3, 4]], columns=['x', 'y'])
操作后C应包含[1,4]和[2,4]。
答案 0 :(得分:4)
在pandas master(或将来的0.13)isin
也会接受DataFrames,但问题是它只是查看每列中的值,而不是列的精确行组合。
取自@AndyHayden的评论(https://github.com/pydata/pandas/issues/4421#issuecomment-23052472),采用类似的方法:
In [3]: mask = pd.Series(map(set(B.itertuples(index=False)).__contains__, A.itertuples(index=False)))
In [4]: A[~mask]
Out[4]:
x y
1 1 4
3 2 4
或者更易阅读的版本:
set_B = set(B.itertuples(index=False))
mask = [x not in set_B for x in A.itertuples(index=False)]
与@ Acorbe的答案相比,这可能带来的好处是保留了A
的索引,并且不会删除A
中的重复行(但这取决于您当然想要的内容)。< / p>
正如我所说,0.13将接受DataFrame到isin
。但是,我不认为这会解决这个问题,因为索引也必须相同:
In [27]: A.isin(B)
Out[27]:
x y
0 True True
1 False True
2 False False
3 False False
您可以通过将其转换为dict来解决此问题,但现在它不会查看两列的组合,而是仅针对每个列:
In [28]: A.isin(B.to_dict(outtype='list'))
Out[28]:
x y
0 True True
1 True True
2 True True
3 False True
答案 1 :(得分:3)
对于那些寻找单栏解决方案的人:
new_df = df1[~df1["column_name"].isin(df2["column_name"])]
〜是NOT的逻辑运算符。
因此,当在df2 [“column_name”]中找不到df1 [“column_name”]的值时,这将创建一个新的数据帧
答案 2 :(得分:0)
一种选择是生成两个sets
,例如A_set
,B_set
,其元素是DataFrames
的行。因此,可以使用快速设置差异操作A_set - B_set
。
A_set = set(map(tuple,A.values)) #we need to have an hashable object before generating a set
B_set = set(map(tuple,B.values))
C_set = A_set - B_set
C_set
{(1, 4), (2, 4)}
C = pd.DataFrame([c for c in C_set], columns=['x','y'])
x y
0 2 4
1 1 4
此程序涉及一些初步转换操作。