比较匹配行的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
进行比较-它是
可以使用任何列名,但不能使用所有列名
列名
注意:这个方法本质上等同于SQLnotin()
当然!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列
中。