小编典典

比较Python Pandas DataFrames以匹配行

python

df1在Pandas中有这个DataFrame():

df1 = pd.DataFrame(np.random.rand(10,4),columns=list('ABCD'))
print df1

       A         B         C         D
0.860379  0.726956  0.394529  0.833217
0.014180  0.813828  0.559891  0.339647
0.782838  0.698993  0.551252  0.361034
0.833370  0.982056  0.741821  0.006864
0.855955  0.546562  0.270425  0.136006
0.491538  0.445024  0.971603  0.690001
0.911696  0.065338  0.796946  0.853456
0.744923  0.545661  0.492739  0.337628
0.576235  0.219831  0.946772  0.752403
0.164873  0.454862  0.745890  0.437729

我想检查中是否df2存在来自另一个数据框()的任何行(所有列)df1。这里是df2

df2 = df1.ix[4:8]
df2.reset_index(drop=True,inplace=True)
df2.loc[-1] = [2, 3, 4, 5]
df2.loc[-2] = [14, 15, 16, 17]
df2.reset_index(drop=True,inplace=True)
print df2

           A         B         C         D
    0.855955  0.546562  0.270425  0.136006
    0.491538  0.445024  0.971603  0.690001
    0.911696  0.065338  0.796946  0.853456
    0.744923  0.545661  0.492739  0.337628
    0.576235  0.219831  0.946772  0.752403
    2.000000  3.000000  4.000000  5.000000
   14.000000 15.000000 16.000000 17.000000

我尝试使用一次df.lookup搜索一行。我这样做是这样的:

list1 = df2.ix[0].tolist()
cols = df1.columns.tolist()
print df1.lookup(list1, cols)

但我收到此错误消息:

  File "C:\Users\test.py", line 19, in <module>
    print df1.lookup(list1, cols)
  File "C:\python27\lib\site-packages\pandas\core\frame.py", line 2217, in lookup
    raise KeyError('One or more row labels was not found')
KeyError: 'One or more row labels was not found'

我也尝试.all()使用:

print (df2 == df1).all(1).any()

但我收到此错误消息:

  File "C:\Users\test.py", line 12, in <module>
    print (df2 == df1).all(1).any()
  File "C:\python27\lib\site-packages\pandas\core\ops.py", line 884, in f
    return self._compare_frame(other, func, str_rep)
  File "C:\python27\lib\site-packages\pandas\core\frame.py", line 3010, in _compare_frame
    raise ValueError('Can only compare identically-labeled '
ValueError: Can only compare identically-labeled DataFrame objects

我也这样尝试过isin()

print df2.isin(df1)

但是我False到处都是,这是不正确的:

    A      B      C      D
False  False  False  False
False  False  False  False
False  False  False  False
False  False  False  False
False  False  False  False
False  False  False  False
False  False  False  False
False  False  False  False
False  False  False  False
False  False  False  False

通过将其与另一个数据框的行进行比较,是否有可能在数据框中搜索一组行?

编辑:df2如果这些行中也存在行,是否可以删除行df1


阅读 210

收藏
2020-12-20

共1个答案

小编典典

解决您的问题的一种可能方法是使用merge。检查df1中是否存在来自另一个数据帧(df2)的任何行(所有列)等同于确定两个数据帧的交集。可以使用以下功能完成此操作:

pd.merge(df1, df2, on=['A', 'B', 'C', 'D'], how='inner')

例如,如果df1是

    A           B            C          D
0   0.403846    0.312230    0.209882    0.397923
1   0.934957    0.731730    0.484712    0.734747
2   0.588245    0.961589    0.910292    0.382072
3   0.534226    0.276908    0.323282    0.629398
4   0.259533    0.277465    0.043652    0.925743
5   0.667415    0.051182    0.928655    0.737673
6   0.217923    0.665446    0.224268    0.772592
7   0.023578    0.561884    0.615515    0.362084
8   0.346373    0.375366    0.083003    0.663622
9   0.352584    0.103263    0.661686    0.246862

df2定义为:

     A          B            C           D
0   0.259533    0.277465    0.043652    0.925743
1   0.667415    0.051182    0.928655    0.737673
2   0.217923    0.665446    0.224268    0.772592
3   0.023578    0.561884    0.615515    0.362084
4   0.346373    0.375366    0.083003    0.663622
5   2.000000    3.000000    4.000000    5.000000
6   14.000000   15.000000   16.000000   17.000000

该函数pd.merge(df1, df2, on=['A', 'B', 'C', 'D'], how='inner')产生:

     A           B           C           D
0   0.259533    0.277465    0.043652    0.925743
1   0.667415    0.051182    0.928655    0.737673
2   0.217923    0.665446    0.224268    0.772592
3   0.023578    0.561884    0.615515    0.362084
4   0.346373    0.375366    0.083003    0.663622

结果是df1和df2中的所有行(所有列)。

如果df1和df2中的列不相同,我们也可以修改此示例,并只比较与列子集相同的行值。如果我们修改原始示例:

df1 = pd.DataFrame(np.random.rand(10,4),columns=list('ABCD'))
df2 = df1.ix[4:8]
df2.reset_index(drop=True,inplace=True)
df2.loc[-1] = [2, 3, 4, 5]
df2.loc[-2] = [14, 15, 16, 17]
df2.reset_index(drop=True,inplace=True)
df2 = df2[['A', 'B', 'C']] # df2 has only columns A B C

然后,我们可以在common_cols = list(set(df1.columns) & set(df2.columns))两个数据框之间使用通用列,然后进行合并:

pd.merge(df1, df2, on=common_cols, how='inner')

编辑:
新问题(评论),从df2中识别出了第一个数据帧(df1)中也存在的行,是否有可能采用pd.merge()的结果,然后从df2中删除行也在df1中

我不知道一种直接的方法来完成从df1中删除也从df2中删除行的任务。也就是说,您可以使用以下代码:

ds1 = set(tuple(line) for line in df1.values)
ds2 = set(tuple(line) for line in df2.values)
df = pd.DataFrame(list(ds2.difference(ds1)), columns=df2.columns)

可能存在一种更好的方式来完成该任务,但我不知道这种方法/功能。

编辑2: 如何从df2中删除也存在于df1中的行,如@WR答案所示。

提供的方法无法解决df2[~df2['A'].isin(df12['A'])]所有类型的情况。考虑以下数据帧:

df1:

   A  B  C  D
0  6  4  1  6
1  7  6  6  8
2  1  6  2  7
3  8  0  4  1
4  1  0  2  3
5  8  4  7  5
6  4  7  1  1
7  3  7  3  4
8  5  2  8  8
9  3  2  8  4

df2:

   A  B  C  D
0  1  0  2  3
1  8  4  7  5
2  4  7  1  1
3  3  7  3  4
4  5  2  8  8
5  1  1  1  1
6  2  2  2  2

df12:

   A  B  C  D
0  1  0  2  3
1  8  4  7  5
2  4  7  1  1
3  3  7  3  4
4  5  2  8  8

将上述DataFrames用于删除df1中也存在的df2中的行将导致以下结果:

   A  B  C  D
0  1  1  1  1
1  2  2  2  2

(1、1、1、1)和(2、2、2、2)行在df2中,而不在df1中。不幸的是,使用提供的方法(df2[~df2['A'].isin(df12['A'])])会导致:

   A  B  C  D
6  2  2  2  2

发生这种情况的原因是,在交集DataFrame(即(1、0、2、3))和df2中都找到了列A中的值1,因此删除了(1、0、2、3)和(1、1, 1
1)。这是意外的,因为(1,1,1,1)行不在df1中,因此不应删除。

我认为以下将提供解决方案。它创建一个伪列,该伪列随后用于将DataFrame子集化为所需结果:

df12['key'] = 'x'
temp_df = pd.merge(df2, df12, on=df2.columns.tolist(), how='left')
temp_df[temp_df['key'].isnull()].drop('key', axis=1)
2020-12-20