Pandas - 缺失值合并

24

看起来pandas合并函数存在一个小问题。它认为NaN值是相等的,并且会将NaN与其他NaN合并:

>>> foo = DataFrame([
    ['a',1,2],
    ['b',4,5],
    ['c',7,8],
    [np.NaN,10,11]
], columns=['id','x','y'])

>>> bar = DataFrame([
    ['a',3],
    ['c',9],
    [np.NaN,12]
], columns=['id','z'])

>>> pd.merge(foo, bar, how='left', on='id')
Out[428]: 
    id   x   y   z
0    a   1   2   3
1    b   4   5 NaN
2    c   7   8   9
3  NaN  10  11  12

[4 rows x 4 columns]

这与我见过的任何关系型数据库不同,通常缺失值会被视为不确定性并且不会被合并在一起,就像它们是相等的一样。这对于稀疏数据集尤其有问题(每个NaN将与其他每个NaN合并,导致一个巨大的DataFrame!)

有没有一种方法可以在合并时忽略缺失值而不必先将它们切片出来?

4个回答

11
你可以在合并时排除值为null的id (以及如果你想要的话,foo)。不确定这是否符合您的要求,因为它们被切片了。
(我已经假设从左连接中,您想保留所有的foo,但只想合并匹配且不为空的bar的部分。)
foo.merge(bar[pd.notnull(bar.id)], how='left', on='id')

Out[11]: 
id   x   y   z
0    a   1   2   3
1    b   4   5 NaN
2    c   7   8   9
3  NaN  10  11 NaN

5
目前我实际上正通过一个变通方法进行这个操作。我想知道是否有选项可以防止pandas似乎执行的“NaN”匹配行为。 - aensm
2
啊,抱歉。我不知道有这样一个东西,但是当涉及到pandas时,总是有新的东西需要学习。 :) - meloncholy
非常感谢,'bar[pd.notnull(bar.id)]' 起作用了。 :) - Vineesh TP
这正是我想要的。非常感谢。 - prem

5
如果您想保留两个表中的NaN而不将它们切片掉,可以使用以下外连接方法:
pd.merge(foo, bar.dropna(subset=['id']), how='outer', on='id')

它基本上返回 foobar 的并集。

3
这个回答不好,因为它没有泛化。dropna()会删除任何一列包含NaN值的所有行,这与预期的行为大相径庭。你需要将其子集化到合并的列中。 - Thomas
2
不错的捕获,已修复。 - yosemite_k

5

如果左右两个数据框中都不需要NaN值,则可以使用以下方式进行合并:

pd.merge(foo.dropna(subset=['id']), bar.dropna(subset=['id']), how='left', on='id')

如果需要在左侧数据框中包含NaN值,则应该使用以下方式:

pd.merge(foo, bar.dropna(subset=['id']), how='left', on='id')

3
这是一个糟糕的答案,因为它没有泛化。dropna()将删除所有包含NaN值的列中的行,这与预期行为大相径庭。您需要将其子集化为合并列! - Thomas

0

另一种方法是执行外连接时保留所有行:

foo['id'] = foo.id.fillna('missing')
pd.merge(foo, bar, how='left', on='id')

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接