在pandas数据框中,针对某一列填充缺失值的高效方法是什么?

4

我需要在数据框的一列中按组进行填充。需要注意的是,每个组的第一个值都是通过构造得到的,因此从不缺失。目前我有以下解决方案。

df = pd.DataFrame({'a': [1,1,2,2,2], 'b': [1, np.nan, 2, np.nan, np.nan]})

# desired output
a   b
1   1
1   1
2   2
2   2
2   2

以下是我迄今为止尝试过的三种解决方案。

# really slow solutions
df['b'] = df.groupby('a')['b'].transform(lambda x: x.fillna(method='ffill'))
df['b'] = df.groupby('a')['b'].fillna(method='ffill')

# much faster solution, but more memory intensive and ugly all around
tmp = df.drop_duplicates('a', keep='first')
df.drop('b', inplace=True, axis=1)
df = df.merge(tmp, on='a')

这三种方法都能产生我期望的输出结果,但前两种在我的数据集上需要很长时间,而第三种解决方案的内存使用更多、感觉相对笨重。是否还有其他方法可以对列进行向前填充?


1
你的真实数据按组排序,就像示例数据一样吗?如果是这样,你应该能够使用常规的 ffill,因为组中的第一个值始终存在,即 df['b'] = df['b'].ffill() - root
哇,我完全错过了这一点。排序后速度非常快。谢谢@root! - 3novak
3个回答

3
您需要按照两个列进行排序 df.sort_values(['a', 'b']).ffill() 以确保稳健性。如果在组内的第一个位置留下了一个 np.nanffill 将使用前一组中的值填充该值。由于 np.nan 将被放置在任何排序的末尾,按 ab 进行排序可确保您不会在任何组的开头遇到 np.nan。然后,您可以使用初始索引进行 .loc.reindex 操作,以恢复原始顺序。

这显然比其他提议要慢一些... 然而,我认为它是正确的,而其他方法则不是。

演示

考虑数据框 df

df = pd.DataFrame({'a': [1,1,2,2,2], 'b': [1, np.nan, np.nan, 2, np.nan]})

print(df)

   a    b
0  1  1.0
1  1  NaN
2  2  NaN
3  2  2.0
4  2  NaN

尝试

df.sort_values('a').ffill()

   a    b
0  1  1.0
1  1  1.0
2  2  1.0  # <--- this is incorrect
3  2  2.0
4  2  2.0

改为:

df.sort_values(['a', 'b']).ffill().loc[df.index]

   a    b
0  1  1.0
1  1  1.0
2  2  2.0
3  2  2.0
4  2  2.0

特别说明
如果整个组有缺失值,这仍然是不正确的。


2
直接使用ffill()会得到最好的结果。以下是比较:
%timeit df.b.ffill(inplace = True)
best of 3: 311 µs per loop

%timeit df['b'] = df.groupby('a')['b'].transform(lambda x: x.fillna(method='ffill'))
best of 3: 2.34 ms per loop

%timeit df['b'] = df.groupby('a')['b'].fillna(method='ffill')
best of 3: 4.41 ms per loop

1
这是什么意思?
df.groupby('a').b.transform('ffill')

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