繁体   English   中英

如何使用集差比较 Pandas DataFrames

[英]How to compare pandas DataFrames using set difference

我有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 都由唯一的行组成。 但是这两个 dfs 之间有一些重叠:

   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 中的任何行,则在两个 dfs 中删除该行。 但这是一种 O(n**2) 方法,需要很长时间。

有没有更pythonic,pandastic的方法来做到这一点?

您可以使用带有indicator=Truemerge

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

如果还需要保留索引,可以在合并前先reset,之后再设置。

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

假设您想比较多组行,您需要将每一行转换为一个可散列对象,ig 元组:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM