当前位置: 首页 > 面试题库 >

比较Python Pandas DataFrames以匹配行

康鹏云
2023-03-14
问题内容

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


问题答案:

解决您的问题的一种可能方法是使用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)


 类似资料:
  • 嗨,我有两个自定义数组列表,我想从一个数组列表中删除与第二个数组列表匹配的类似项。

  • 这里有2个测量: 正如您所见,比较两个匹配的字符串比比较两个大小相同但不匹配的字符串要快。这是非常令人不安的:在字符串比较期间,我认为python是逐字符测试字符串的,所以应该比更长,因为它需要对1进行4次测试才能进行不匹配的比较。可能比较是基于哈希的,但在这种情况下,两种比较的计时应该相同。 你知道为什么吗?

  • 我有两个文件file1。txt和file2。txt。 文件1。文本 file2.txt 我想匹配文件1的第1、2和3列。带有文件2第1、4和5列的txt。txt。如果匹配,则将匹配行与以下行一起打印,直到,但不要打印。我用“awk”命令试过了

  • 问题内容: 我有以下代码 这是输出 现在我意识到float和int是不同的,但是考虑到四舍五入,我本来希望两个值匹配。我已经通过强制转换为int解决了它。 所以我的问题是,为什么这个比较不能像我期望的那样工作(两个值都匹配)? 问题答案: 请注意PHP手册中的 红色大警告 ! 比较浮点数时不要指望任何东西。即使精度为0,舍入结果仍然是浮点数。在您的特定情况下,碰巧结果要比预期的大一点,因此强制转换

  • 问题内容: 我想知道如何比较两个不同的数据库 表记录 。我的意思是,我将比较两个数据库表,它们可能具有不同的列名但具有相同的数据。但是其中一个表可能比另一个表具有更多的记录,因此我想看看这两个表之间的区别是什么。为此,如何编写sql查询?仅供参考:这两个数据库都在同一个SQL Server实例下。 然后,在比较表1和表2之后,它应该 从 表2返回 Ruby Core。 问题答案: 如果执行从T1到

  • 我有以下课程: 现在我想在下面的测试中使用Hamcrest Matcher(它只是一个简化的示例): 但我也犯了同样的错误。 我使用的是Hamcrest 1.3版