Python 用于正向填充数据帧列中缺失值的有效解决方案?

Python 用于正向填充数据帧列中缺失值的有效解决方案?,python,pandas,missing-data,Python,Pandas,Missing Data,我需要在组内的数据帧的列中转发填充值。我应该注意到,组中的第一个值在构造时从未丢失。目前我有以下解决方案 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'

我需要在组内的数据帧的列中转发填充值。我应该注意到,组中的第一个值在构造时从未丢失。目前我有以下解决方案

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')
所有这三种方法都会产生我想要的输出,但前两种方法在我的数据集上花费了很长的时间,第三种方法更占用内存,而且感觉相当笨拙。是否有其他方法可以向前填充列?

这是什么方法

df.groupby('a').b.transform('ffill')
直接使用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

您需要按两列对df.sort_值(['a',b']).ffill()进行排序,以确保健壮性。如果一个
np.nan
留在组中的第一个位置,
ffill
将用前一个组中的值填充该位置。由于
np.nan
将放在任何排序的末尾,因此通过
a
b
进行排序可确保您不会将
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
试一试

特别注意事项

如果整个组缺少值,这仍然是不正确的

您的真实数据是否按组排序,如示例数据所示?如果是这样的话,您应该能够只访问一个常规的
ffill
,因为组中的第一个值始终存在,即
df['b']=df['b'].ffill()
.Wow。我完全错过了。分类后,它的闪电般的快。谢谢@root!
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