比较匹配行的Python数据帧

比较匹配行的Python数据帧,python,pandas,rows,matching,Python,Pandas,Rows,Matching,我在熊猫中有这个数据帧(df1): 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.8

我在熊猫中有这个数据帧(
df1
):

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'
  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
但我得到了这个错误信息:

  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'
  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
但是我得到了
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
是否可以通过将数据帧中的一组行与另一个数据帧的行进行比较来搜索该数据帧中的一组行

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

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

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\u cols=list(set(df1.columns)&set(df2.columns))
查看公共列,然后合并:

pd.merge(df1, df2, on=common_cols, how='inner')
编辑:新问题(注释),在确定了df2中也出现在第一个数据帧(df1)中的行之后,是否可以获取pd.merge()的结果,然后删除df2中也出现在df1中的行

我不知道有什么简单的方法可以完成从df2中删除同样存在于df1中的行的任务。也就是说,您可以使用以下方法:

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)
   A  B  C  D
0  1  1  1  1
1  2  2  2  2
可能有更好的方法来完成这项任务,但我不知道有这样的方法/功能

编辑2:如何从df2中删除同样存在于df1中的行,如@WR answer所示

提供的方法不适用于所有类型的情况。考虑下面的数据框:

df1:

df2:

df12:

使用上述数据帧以从df2中删除同样存在于df1中的行,将导致以下结果:

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)
   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
发生这种情况是因为列A中的值1在交叉点数据帧(即(1,0,2,3))和df2中都存在,因此删除了(1,0,2,3)和(1,1,1,1)。这是无意的,因为行(1,1,1,1)不在df1中,不应删除

我认为下面将提供一个解决方案。它创建一个虚拟列,稍后用于将数据帧子集为所需的结果:

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)

@Andrew:我相信我找到了一种方法,可以删除一个数据帧中已经存在于另一个数据帧中的行(即回答我的编辑),而不使用循环-如果您不同意和/或我的OP+编辑没有明确说明这一点,请告诉我:

这很有效

两个数据帧的列始终相同-
A
B
C
D
。考虑到这一点,在很大程度上基于Andrew的方法,下面是如何从
df2
中删除同样出现在
df1
中的行:

common_cols = df1.columns.tolist()                         #generate list of column names
df12 = pd.merge(df1, df2, on=common_cols, how='inner')     #extract common rows with merge
df2 = df2[~df2['A'].isin(df12['A'])]
第3行执行以下操作:

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)
   A  B  C  D
0  1  1  1  1
1  2  2  2  2
  • 仅从
    df2
    中提取与
    df1
    中的行不匹配的行:
  • 为了使两行不同,一行中的任何一列必须
    必须与另一列中对应的列不同 划船
  • 在这里,我选择了列
    A
    进行比较-它是
    可以使用任何列名,但不能使用所有列名 列名

注意:这个方法本质上等同于SQL
notin()

当然!SQL
内部联接
。我没想到。一个问题是,我从未在多个列上使用过
JOIN
ing
。如果要检查数据帧的所有列,您是否可以将
on=['A','B','C','D']
替换为
on=df1.columns
?您可以使用
on=list(df1.columns)
或等效的
on=list(df2.columns)
。如果要检查行是否相同(所有列),df1和df2中的列必须相同。Andrew,最后一个问题(我也将其添加到原始帖子中)-在识别了第一个数据帧(
df1
)中也存在的
df2
中的行之后,是否可以获取
pd.merge()的结果
然后从
df2
中删除同样出现在
df1
中的行。在编辑2中,现在似乎有两个起始数据帧,分别为
df12
df2
。你的意思是说
df2['key']='x'
temp_df=pd.merge(df2,df1,on=df2.col……
。从上面的例子来看,pd.merge()应该生成max(len(df1),len(df2))
?我缺少了什么?你无法想象我浪费了多少时间试图使用循环来完成这个任务。我想你的逻辑可能有问题(虽然我可能误解了您期望的结果)我已相应地更新了我的答案。您是正确的。您的答案是更好的解决方案。感谢您向我指出这一点。“~”运算符在本推荐中的含义是什么?df2=df2[~df2['a'].isin(df12['a'])]它意味着
df2
中的
A列
值不在
df12
中的
A列
中。