如何从另一个数据帧中删除pandas数据帧

时间:2016-05-19 03:54:18

标签: python pandas dataframe subtraction

如何从另一个数据帧中删除pandas数据帧,就像set subtraction:

一样
a=[1,2,3,4,5]
b=[1,5]
a-b=[2,3,4]

现在我们有两个pandas数据帧,如何从df1中删除df2:

In [5]: df1=pd.DataFrame([[1,2],[3,4],[5,6]],columns=['a','b'])
In [6]: df1
Out[6]:
   a  b
0  1  2
1  3  4
2  5  6


In [9]: df2=pd.DataFrame([[1,2],[5,6]],columns=['a','b'])
In [10]: df2
Out[10]:
   a  b
0  1  2
1  5  6

然后我们期望df1-df2结果为:

In [14]: df
Out[14]:
   a  b
0  3  4

怎么做?

谢谢。

8 个答案:

答案 0 :(得分:26)

解决方案

使用pd.concat后跟drop_duplicates(keep=False)

pd.concat([df1, df2, df2]).drop_duplicates(keep=False)

看起来像是

   a  b
1  3  4

解释

pd.concat将两个DataFrame添加到一起,方法是将一个drop_duplicates添加到另一个之后。如果有任何重叠,它将由drop_duplicates方法捕获。但是,keep=False默认情况下会留下第一个观察结果,并删除所有其他观察结果。在这种情况下,我们希望删除每个副本。因此,df2参数就是这样做的。

重复df2的特别说明。只有一个df2 df1中不在df2中的任何行不会被视为重复且仍将保留。只有一个df2的此解决方案仅在df1df2的子集时才有效。但是,如果我们连续两次{ test: /\.(png|jpg)$/, loader: 'url?limit=8192' } ,则保证会重复,然后会被删除。

答案 1 :(得分:6)

你可以使用.duplicated,它具有相当富有表现力的好处:

%%timeit
combined = df1.append(df2)
combined[~combined.index.duplicated(keep=False)]

1000 loops, best of 3: 875 µs per loop

进行比较:

%timeit df1.loc[pd.merge(df1, df2, on=['a','b'], how='left', indicator=True)['_merge'] == 'left_only']

100 loops, best of 3: 4.57 ms per loop


%timeit pd.concat([df1, df2, df2]).drop_duplicates(keep=False)

1000 loops, best of 3: 987 µs per loop


%timeit df2[df2.apply(lambda x: x.value not in df2.values, axis=1)]

1000 loops, best of 3: 546 µs per loop

总之,使用np.array比较最快。那里不需要.tolist()

答案 2 :(得分:2)

设定逻辑方法。将df1df2的行转换为集合。然后使用set减法来定义新的DataFrame

idx1 = set(df1.set_index(['a', 'b']).index)
idx2 = set(df2.set_index(['a', 'b']).index)

pd.DataFrame(list(idx1 - idx2), columns=df1.columns)

   a  b
0  3  4

答案 3 :(得分:2)

从问题中合并df1和df2我的镜头。

使用'指标'参数

In [74]: df1.loc[pd.merge(df1, df2, on=['a','b'], how='left', indicator=True)['_merge'] == 'left_only']
Out[74]: 
   a  b
1  3  4

答案 4 :(得分:1)

掩蔽方法

df1[df1.apply(lambda x: x.values.tolist() not in df2.values.tolist(), axis=1)]

   a  b
1  3  4

答案 5 :(得分:0)

我认为需要删除第一个tolist(),但保留第二个:

df1[df1.apply(lambda x: x.values() not in df2.values.tolist(), axis=1)]

答案 6 :(得分:0)

最简单的选择是使用索引。

  1. 附加df1和df2并重置其索引。

    df = df1.concat(df2)
    df.reset_index(inplace=True)

  2. 例如:
    这将给出df2索引

    indexes_df2 = df.index[ (df["a"].isin(df2["a"]) ) & (df["b"].isin(df2["b"]) ) result_index = df.index[~index_df2] result_data = df.iloc[ result_index,:]

希望它对新读者有所帮助,尽管这个问题是在不久前发布的:)

答案 7 :(得分:0)

要获取包含所有在DF1中但不在DF2中的记录的数据框

DF = DF1 [〜DF1.isin(DF2)]。dropna(how ='all')