Pandas 识别不在另一个数据帧中的记录

Pandas 识别不在另一个数据帧中的记录,pandas,merge,Pandas,Merge,我有一个这样的数据帧: data1 = pd.DataFrame([['a','z',0],['a','y',20],['b','z',1]],columns=['id1','id2','number']) data2 = pd.DataFrame([['a','y',1],['a','y',1],['b','z',0]],columns=['id1','id2','number']) 我想返回data1中而不是data2中的记录(由id1和id2连接) 在这种情况下,我只希望它返回一条记录[

我有一个这样的数据帧:

data1 = pd.DataFrame([['a','z',0],['a','y',20],['b','z',1]],columns=['id1','id2','number'])
data2 = pd.DataFrame([['a','y',1],['a','y',1],['b','z',0]],columns=['id1','id2','number'])
我想返回data1中而不是data2中的记录(由id1和id2连接)


在这种情况下,我只希望它返回一条记录['a','z',0],因为['a','y']和['b','z']都存在于数据2中。

这一条有点棘手,通常当我们想使用多个条件过滤掉行时,我们会这样做:

In [39]:
data1[(data1.id1 != data2.id1) & (data1.id2 != data2.id2)]
Out[39]:
Empty DataFrame
Columns: [id1, id2, number]
Index: []
但这不会产生任何行,因为至少有一个id值匹配,因此不满足条件

因此,我们真正想要的是使用这两列作为id列,然后过滤掉仅在data1中的行

为此,我们可以先执行左合并:

In [33]:
merged = data1.merge(data2, on=['id1', 'id2'], how='left')
merged
Out[33]:
  id1 id2  number_x  number_y
0   a   z         0       NaN
1   a   y        20         1
2   a   y        20         1
3   b   z         1         0
现在我们只需要右侧为null的行,因为这表明复合索引值不存在:

In [36]:

merged_null = merged[merged.number_y.isnull()]
merged_null

Out[36]:
  id1 id2  number_x  number_y
0   a   z         0       NaN
现在,我们可以使用它从原始数据帧中选择行,使用
isin
选择id1和id2中的id值:

In [38]:

data1[(data1.id1.isin(merged_null['id1']) ) & (data1.id2.isin(merged_null['id2']))]
Out[38]:
  id1 id2  number
0   a   z       0

我认为还有另一种方法。如果我们将两列都设置为索引,则可以使用
.isin
方法筛选出所需内容:

data1.set_index(['id1', 'id2'], inplace=True)
data2.set_index(['id1', 'id2'], inplace=True)
data1[~data1.index.isin(data2.index)].reset_index()
收益率:

  id1 id2  number
0   a   z       0

不管你在
号码中有什么

很好!现在,如果我的数字y可以有空值进入合并呢?是否有其他方法可以检测连接是否成功?关键是检测lhs中何时不存在rhs,在这种情况下,您仍然会有列冲突,因此我猜您可以在所有列与筛选的合并df值匹配的位置进行筛选,例如在
merged\u null
步骤之后,将
'number\u x'
重命名回
'number'
下拉列
number\u y
,您可以执行反向合并:`merged\u null.merge(数据1,on=['id1','id2','number','how='left')这将确保现在只保留有效的行,谢谢!我很惊讶我必须两次传递数据,但这是有效的。@Chris我想你必须从数据数组而不是db表的角度来考虑。dataframes和dbs之间的功能类似,但不相同,所以你必须这样做才能实现你想要的这两种方法都有效,但对我来说这似乎有点优雅。谢谢!