熊猫获取不在其他数据框中的行

新手上路,请多包涵

我有两个 pandas 数据框,它们有一些共同的行。

假设 dataframe2 是 dataframe1 的子集。

如何获取不在 dataframe2 中的 dataframe1 行?

 df1 = pandas.DataFrame(data = {'col1' : [1, 2, 3, 4, 5], 'col2' : [10, 11, 12, 13, 14]})
df2 = pandas.DataFrame(data = {'col1' : [1, 2, 3], 'col2' : [10, 11, 12]})

df1

    col1  col2
0     1    10
1     2    11
2     3    12
3     4    13
4     5    14

df2

    col1  col2
0     1    10
1     2    11
2     3    12

预期结果:

    col1  col2
3     4    13
4     5    14

原文由 think nice things 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 366
2 个回答

一种方法是将内部合并的结果存储在两个 dfs 中,然后当一列的值不在这个 common 中时,我们可以简单地选择行:

 In [119]:

common = df1.merge(df2,on=['col1','col2'])
print(common)
df1[(~df1.col1.isin(common.col1))&(~df1.col2.isin(common.col2))]
   col1  col2
0     1    10
1     2    11
2     3    12
Out[119]:
   col1  col2
3     4    13
4     5    14

编辑

您发现的另一种方法是使用 isin 这将产生 NaN 您可以删除的行:

 In [138]:

df1[~df1.isin(df2)].dropna()
Out[138]:
   col1  col2
3     4    13
4     5    14

但是,如果 df2 不以相同的方式开始行,那么这将不起作用:

 df2 = pd.DataFrame(data = {'col1' : [2, 3,4], 'col2' : [11, 12,13]})

将产生整个 df:

 In [140]:

df1[~df1.isin(df2)].dropna()
Out[140]:
   col1  col2
0     1    10
1     2    11
2     3    12
3     4    13
4     5    14

原文由 EdChum 发布,翻译遵循 CC BY-SA 3.0 许可协议

当前选择的解决方案产生不正确的结果。为了正确解决这个问题,我们可以执行从 df1df2 的左连接,确保首先只获取 df2 -d5 的唯一行

首先,我们需要修改原始 DataFrame 以添加包含数据 [3, 10] 的行。

 df1 = pd.DataFrame(data = {'col1' : [1, 2, 3, 4, 5, 3],
                           'col2' : [10, 11, 12, 13, 14, 10]})
df2 = pd.DataFrame(data = {'col1' : [1, 2, 3],
                           'col2' : [10, 11, 12]})

df1

   col1  col2
0     1    10
1     2    11
2     3    12
3     4    13
4     5    14
5     3    10

df2

   col1  col2
0     1    10
1     2    11
2     3    12

执行左连接,消除 --- 中的重复项,以便 df2 的每一行恰好与 df1 df2 的 1 行连接使用参数 indicator 返回一个额外的列,指示该行来自哪个表。

 df_all = df1.merge(df2.drop_duplicates(), on=['col1','col2'],
                   how='left', indicator=True)
df_all

   col1  col2     _merge
0     1    10       both
1     2    11       both
2     3    12       both
3     4    13  left_only
4     5    14  left_only
5     3    10  left_only

创建一个布尔条件:

 df_all['_merge'] == 'left_only'

0    False
1    False
2    False
3     True
4     True
5     True
Name: _merge, dtype: bool


为什么其他解决方案是错误的

一些解决方案犯了同样的错误——它们只检查每列中的每个值是否独立,而不是在同一行中。添加最后一行,这是唯一的,但具有来自 df2 的两列的值暴露了错误:

 common = df1.merge(df2,on=['col1','col2'])
(~df1.col1.isin(common.col1))&(~df1.col2.isin(common.col2))
0    False
1    False
2    False
3     True
4     True
5    False
dtype: bool

此解决方案得到相同的错误结果:

 df1.isin(df2.to_dict('l')).all(1)

原文由 Ted Petrou 发布,翻译遵循 CC BY-SA 4.0 许可协议

推荐问题