如何使用设置差异比较熊猫数据框

时间:2019-02-04 00:06:05

标签: python python-3.x pandas dataframe set

我有df1df2

df1 = pd.DataFrame([[1,1,1,1],[2,2,1,1],[0,0,1,1],[1,1,1,1],[2,2,1,1],[0,0,4,1]], 
                   columns=['col1','col2','col3','col4'])
df2 = pd.DataFrame([[1,1,1,1],[3,3,1,1],[0,0,1,1],[1,1,5,1],[3,3,1,1],[0,0,1,1]], 
                   columns=['col1','col2','col3','col4'])

我删除了重复的行:

df1 = df1.drop_duplicates(subset=['col1', 'col2', 'col3'])
df2 = df2.drop_duplicates(subset=['col1', 'col2', 'col3'])

因此每个df由唯一的行组成。但是两个df之间有一些重叠:

   col1  col2  col3  col4
0     1     1     1     1
1     2     2     1     1
2     0     0     1     1
5     0     0     4     1

   col1  col2  col3  col4
0     1     1     1     1
1     3     3     1     1
2     0     0     1     1
3     1     1     5     1

我的实际df1df2的形状大约为(5000000,23),并包含int,float和object字段。


开始编辑: 我想创建df1_uniq(在df1中但不在df2中)和df2_uniq(在df2中但不在df1中。)

df1_iniq:
   col1  col2  col3  col4
1     2     2     1     1
5     0     0     4     1

df2_uniq:
   col1  col2  col3  col4
1     3     3     1     1
3     1     1     5     1

结束编辑


在集合符号中,我认为这将是df1.difference(df2)df2.difference(df1),但是运行该代码时会得到空集合。请注意,比较每个df 工作中的单个col,例如

set(df_1[field].unique()).difference(set(df_2[field].unique()))

返回[2]

另一种方法是遍历每个df,如果df1 [i]等于df2中的任何行,则将该行都放在两个df中。但这是一种O(n ** 2)方法,将需要很长时间。

是否还有更Python化,泛滥的方式来做到这一点?

2 个答案:

答案 0 :(得分:2)

您可以将mergeindicator=True结合使用:

u = df1.merge(df2, how='outer', indicator=True)
df3 = u.query('_merge == "left_only"').drop('_merge', 1)
df4 = u.query('_merge == "right_only"').drop('_merge', 1)

df3

   col1  col2  col3  col4
1     2     2     1     1
3     0     0     4     1

df4

   col1  col2  col3  col4
4     3     3     1     1
5     1     1     5     1

如果df1df2的列名不同,请确保它们都相同:

df1.columns = df2.columns

如果还需要保留索引,则可以在合并之前先将其重置,然后再进行设置。

u, v = df1.reset_index(), df2.reset_index()
w = (u.merge(v, how='outer', on=df1.columns.tolist(), indicator=True)
      .fillna({'index_x': -1, 'index_y': -1}, downcast='infer'))
w

   index_x  col1  col2  col3  col4  index_y      _merge
0        0     1     1     1     1        0        both
1        1     2     2     1     1       -1   left_only
2        2     0     0     1     1        2        both
3        5     0     0     4     1       -1   left_only
4       -1     3     3     1     1        1  right_only
5       -1     1     1     5     1        3  right_only

现在,

df3 = (w.query('_merge == "left_only"')
        .set_index('index_x')
        .drop(['_merge', 'index_y'], 1)
        .rename_axis([None], axis=0))
df4 = (w.query('_merge == "right_only"')
        .set_index('index_y')
        .drop(['_merge', 'index_x'], 1)
        .rename_axis([None], axis=0))

df3

   col1  col2  col3  col4
1     2     2     1     1
5     0     0     4     1

df4

   col1  col2  col3  col4
1     3     3     1     1
3     1     1     5     1

答案 1 :(得分:0)

假设您要比较行集,则需要将每行转换为可哈希的对象,例如元组:

set([tuple(x) for x in df1.values]) - set([tuple(x) for x in df2.values])