查找df1('col1')中的值是否等于df2('col3')中的任何值,并在条件为True时从df1中删除行[Python]

11 浏览
0 Comments

查找df1('col1')中的值是否等于df2('col3')中的任何值,并在条件为True时从df1中删除行[Python]

我有两个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('col1')中的值是否与df2('col3')中的任何值相等,从df1中移除相应的行?

在解决这个问题之前,我们需要做一些假设。假设数据框df1和df2的索引是一致的(不考虑实际的列值)。

解决方法:使用索引的差集操作。

代码如下:

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

这行代码的作用是,根据df1的索引是否在df2的索引中,来选择是否保留该行。如果索引在df2中不存在,则保留该行;如果索引在df2中存在,则移除该行。

通过使用`~df1.index.isin(df2.index)`,我们得到了一个布尔值的Series,其中为True的位置表示该行在df1中的索引不在df2中的索引中。

最后,我们使用`df1[~df1.index.isin(df2.index)]`来选择保留在df1中索引不在df2中的索引中的行,从而实现了根据df1('col1')的值是否与df2('col3')的值相等来移除行的目的。

值得注意的是,以上代码只考虑了索引是否一致,没有考虑实际的列值。如果需要考虑列值是否相等来决定是否移除行,可以使用类似的方法。

0
0 Comments

问题出现的原因是需要从df1中找出col1列的值与df2中col3列的任何值相等的行,并将这些行从df1中删除。解决方法有两种:

方法一:

1. 使用内连接将df1和df2进行合并,将合并结果存储在common变量中。

2. 通过筛选出col1和col2列的值不在common中的行来得到结果。

方法二:

1. 使用isin函数判断df1中的每个元素是否在df2中。

2. 将isin函数的结果取反,并使用dropna函数删除含有NaN值的行。

然而,如果df2中的行与df1的行的顺序不同,则第二种方法将无法得到正确结果。可以使用dropna函数的参数how='all'来解决这个问题。

另外,~符号在代码df1[~df1.isin(df2)]中表示取反操作,即选择不在df2中的元素。

根据不同的需求选择合适的方法来解决问题。

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']`来得到包含结果的DataFrame。

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

有可能获得"left-only"的计数吗?

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

0