如何获取两个数据帧之间的差异行?

13 浏览
0 Comments

如何获取两个数据帧之间的差异行?

我有两个pandas数据帧,它们有一些共同的行。\n假设dataframe2是dataframe1的子集。\n如何获取dataframe1中不在dataframe2中的行?\n

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]})

\ndf1\n

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

\ndf2\n

   col1  col2
0     1    10
1     2    11
2     3    12

\n期望结果:\n

   col1  col2
3     4    13
4     5    14

0
0 Comments

原因:

问题的出现是因为用户想要找到两个数据框之间的差异行。

解决方法:

下面的代码可以帮助用户找到两个数据框之间的不同行:

df1[~df1.index.isin(df2.index)]

0
0 Comments

如何获取两个数据帧之间的不同行?

有一种方法是将内部合并的结果从两个数据帧中存储起来,然后我们可以简单地选择那些一列的值不在这个共同的值中的行:

common = df1.merge(df2,on=['col1','col2'])
print(common)
df1[(~df1.col1.isin(common.col1))&(~df1.col2.isin(common.col2))]

另一种方法是使用`isin`,它会产生`NaN`的行,然后可以将这些行删除:

df1[~df1.isin(df2)].dropna()

然而,如果df2的行不是以相同的方式开始的,这种方法就不起作用:

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

将会产生整个df:

df1[~df1.isin(df2)].dropna()

`df1[~df1.isin(df2)].dropna(how = 'all')`似乎可以解决这个问题。不管怎样,你的答案帮助我找到了一个解决办法。

你能解释一下你的代码`df1[~df1.isin(df2)]`中的`~`是什么意思吗?我无法从中找到任何有关的信息,因为它只是一个符号。谢谢。

它是否是否定了表达式,基本上它表示选择所有不在其中而不是在其中的值。

另外,这可能更简单一些:`df1[~df1.index.isin(df2.index)]`。

0
0 Comments

问题:如何获得两个数据框之间的差异行?

原因:当前选择的解决方案产生了错误的结果。为了正确解决这个问题,我们可以将df1左连接到df2上,确保首先获取df2的唯一行。

解决方法:

首先,我们需要修改原始的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的恰好一行进行连接。使用参数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)

但我认为,他们假设col1是唯一的索引(问题中没有提到,但是很明显)。因此,如果从来没有出现col1的两个值具有相同的col2值的情况(不可能有两行col1=3),上面的答案是正确的。

这显然并不明显,所以你的观点是无效的。我的解决方案适用于更多的情况。

问题:创建一个切片是否比创建一个布尔数组更容易?因为目标是获取行。

使用df_all[df_all['_merge'] == 'left_only']可以得到结果的数据框。

对于新来的人,添加了没有解释的额外行是令人困惑的。然后使这个解决方案更好。此外,我建议使用how='outer',这样_merge列就有了left/right/both,当未来的读者尝试将解决方案应用到他们的问题时,更易于理解。

能否获取“left-only”的计数?

为什么需要.drop_duplicates()?我没有看到DF中有任何重复行。

0