为熊猫设定差异

问题描述 投票:33回答:10

一个简单的熊猫问题:

是否有drop_duplicates()功能可以删除复制中涉及的每一行?

一个等价的问题如下:pandas对数据帧有不同的设置吗?

例如:

In [5]: df1 = pd.DataFrame({'col1':[1,2,3], 'col2':[2,3,4]})

In [6]: df2 = pd.DataFrame({'col1':[4,2,5], 'col2':[6,3,5]})

In [7]: df1
Out[7]: 
   col1  col2
0     1     2
1     2     3
2     3     4

In [8]: df2
Out[8]: 
   col1  col2
0     4     6
1     2     3
2     5     5

所以像df2.set_diff(df1)这样的东西会产生这样的:

   col1  col2
0     4     6
2     5     5

但是,我不想依赖索引,因为在我的情况下,我必须处理具有不同索引的数据帧。

顺便说一句,我最初想到了当前drop_duplicates()方法的扩展,但现在我意识到使用集合论属性的第二种方法通常会更有用。但是,这两种方法都解决了我当前的问题

谢谢!

python pandas dataframe
10个回答
24
投票
from pandas import  DataFrame

df1 = DataFrame({'col1':[1,2,3], 'col2':[2,3,4]})
df2 = DataFrame({'col1':[4,2,5], 'col2':[6,3,5]})

print df2[~df2.isin(df1).all(1)]
print df2[(df2!=df1)].dropna(how='all')
print df2[~(df2==df1)].dropna(how='all')

0
投票

即使您在两个数据帧中都有多个列,这也应该有效。但请确保两个数据帧的列名完全相同。

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

使用多列,您还可以使用:

col_names=['col_1','col_2']
set_difference = pd.concat([df2[col_names], df1[col_names], 
df1[col_names]]).drop_duplicates(keep=False)

38
投票

有点复杂,但如果你想完全忽略索引数据。将数据帧的内容转换为包含列的元组集:

ds1 = set([tuple(line) for line in df1.values])
ds2 = set([tuple(line) for line in df2.values])

此步骤也将删除数据帧中的任何重复项(忽略索引)

set([(1, 2), (3, 4), (2, 3)])   # ds1

然后可以使用set方法来查找任何内容。例如找出差异:

ds1.difference(ds2)

给出:set([(1,2),(3,4)])

如果需要,可以将其恢复为数据帧。注意必须将set转换为list 1st,因为set不能用于构造数据帧:

pd.DataFrame(list(ds1.difference(ds2)))

20
投票

这是保持索引的另一个答案,并且在两个数据帧中不需要相同的索引。

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

它很快,结果是

   col1  col2
0     4     6
2     5     5

4
投票

通过要映射的对象的列应用(df2);找到不在集合中的行(isin就像集合运算符)

In [32]: df2.apply(lambda x: df2.loc[~x.isin(df1[x.name]),x.name])
Out[32]: 
   col1  col2
0     4     6
2     5     5

同样的事情,但包括df1中的所有值,但仍然是df2中的每列

In [33]: df2.apply(lambda x: df2.loc[~x.isin(df1.values.ravel()),x.name])
Out[33]: 
   col1  col2
0   NaN     6
2     5     5

第二个例子

In [34]: g = pd.DataFrame({'x': [1.2,1.5,1.3], 'y': [4,4,4]})

In [35]: g.columns=df1.columns

In [36]: g
Out[36]: 
   col1  col2
0   1.2     4
1   1.5     4
2   1.3     4

In [32]: g.apply(lambda x: g.loc[~x.isin(df1[x.name]),x.name])
Out[32]: 
   col1  col2
0   1.2   NaN
1   1.5   NaN
2   1.3   NaN

注意,在0.13中,在帧级上将有一个isin运算符,所以类似于:df2.isin(df1)应该是可能的


3
投票

获取合并的交集索引,然后删除它们:

>>> df_all = pd.DataFrame(np.arange(8).reshape((4,2)), columns=['A','B']); df_all
   A  B
0  0  1
1  2  3
2  4  5
3  6  7
>>> df_completed = df_all.iloc[::2]; df_completed
   A  B
0  0  1
2  4  5
>>> merged = pd.merge(df_all.reset_index(), df_completed); merged
   index  A  B
0      0  0  1
1      2  4  5
>>> df_pending = df_all.drop(merged['index']); df_pending
   A  B
1  2  3
3  6  7

3
投票

有3种方法可行,但其中有两种方法存在缺陷。

方法1(哈希方法):

它适用于我测试的所有情况。

df1.loc[:, "hash"] = df1.apply(lambda x: hash(tuple(x)), axis = 1)
df2.loc[:, "hash"] = df2.apply(lambda x: hash(tuple(x)), axis = 1)
df1 = df1.loc[~df1["hash"].isin(df2["hash"]), :]

方法2(Dict方法):

如果DataFrame包含datetime列,则会失败。

df1 = df1.loc[~df1.isin(df2.to_dict(orient="list")).all(axis=1), :]

方法3(MultiIndex方法):

我遇到了使用None或NaN的列失败的情况。

df1 = df1.loc[~df1.set_index(list(df1.columns)).index.isin(df2.set_index(list(df2.columns)).index)

2
投票

假设:

  1. df1和df2具有相同的列
  2. 它是一个设置操作,因此忽略重复项
  3. 集合不是非常大,所以你不用担心内存
union = pd.concat([df1,df2])
sym_diff = union[~union.duplicated(keep=False)]
union_of_df1_and_sym_diff = pd.concat([df1, sym_diff])
diff = union_of_df1_and_sym_diff[union_of_df1_and_sym_diff.duplicated()]

2
投票

Pandas MultiIndex对象具有作为方法实现的快速设置操作,因此您可以将DataFrames转换为MultiIndexes,使用difference()方法,然后将结果转换回DataFrame。这个解决方案应该比目前给出的解决方案快得多(比我的简短测试大约100倍或更多),并且它不依赖于原始帧的行索引。正如Piotr提到的那样,由于np.nan!= np.nan,因此无法使用null值。 df2中具有空值的任何行总是出现在差异中。此外,两个DataFrame的列的顺序应相同。

df1mi = pd.MultiIndex.from_arrays(df1.values.transpose(), names=df1.columns)
df2mi = pd.MultiIndex.from_arrays(df2.values.transpose(), names=df2.columns)
dfdiff = df2mi.difference(df1mi).to_frame().reset_index(drop=True)

1
投票

我不确定pd.concat()如何隐式加入重叠列,但我不得不对@radream的答案做一点调整。

从概念上讲,多列上的集合差异(symmetric)是集合并(外部联接)减去集合交集(或内部联接):

df1 = pd.DataFrame({'col1':[1,2,3], 'col2':[2,3,4]})
df2 = pd.DataFrame({'col1':[4,2,5], 'col2':[6,3,5]})
o = pd.merge(df1, df2, how='outer')
i = pd.merge(df1, df2)
set_diff = pd.concat([o, i]).drop_duplicates(keep=False)

这会产生:

   col1  col2
0     1     2
2     3     4
3     4     6
4     5     5
© www.soinside.com 2019 - 2024. All rights reserved.