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

时间:2014-11-24 03:36:32

标签: 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连接)。

在这种情况下,我只想让它返回一条记录[' a'' z',0],因为两者都是[' a',& #39; y']和[' b'' z']确实存在于data2中。

2 个答案:

答案 0 :(得分:4)

我认为还有另一种方式。如果我们将两列都设置为索引,我们可以使用.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

无论您在number中拥有什么。

答案 1 :(得分:1)

这个有点棘手,通常当我们想要使用多个条件过滤掉行时,我们会做类似的事情:

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

现在我们只需要右侧为空的行,因为这表示复合索引值不存在:

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 ad 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