在Pandas分组DataFrame中获取前序最大及后序最小非缺失值
问题描述
我有一个带分组结构的Pandas DataFrame,其中目标列val在分组内已排序,但存在缺失值需要界定。原始数据如下:
group_id id_within_group val 1 1 3.2 1 2 4.8 1 3 5.2 1 4 NaN 1 5 7.5 2 1 1.8 2 2 2.8 2 3 NaN 2 4 5.4 2 5 6.2
需要生成下界列max_prev(当前行所在分组中前序所有行的最大值)和min_next(当前行所在分组中后序所有行的最小值)。由于可能存在连续NaN,不能仅查看相邻行,无需处理分组内首尾行的边界情况,期望输出如下:
group_id id_within_group val max_prev min_next 1 1 3.2 NaN 4.8 1 2 4.8 3.2 5.2 1 3 5.2 4.8 7.5 1 4 NaN 5.2 7.5 1 5 7.5 5.2 NaN 2 1 1.8 NaN 2.8 2 2 2.8 1.8 5.4 2 3 NaN 2.8 5.4 2 4 5.4 2.8 6.2 2 5 6.2 5.4 NaN
解决方案
利用Pandas的分组操作和填充功能可以高效实现需求,核心思路是:
- 由于
val在分组内已按升序排列,前序所有行的最大值等价于当前行之前最后一个非NaN值,可通过向前填充(ffill)+移位实现; - 后序所有行的最小值等价于当前行之后第一个非NaN值,可通过向后填充(bfill)+移位实现。
具体代码如下:
import pandas as pd # 构造原始数据 data = { 'group_id': [1,1,1,1,1,2,2,2,2,2], 'id_within_group': [1,2,3,4,5,1,2,3,4,5], 'val': [3.2,4.8,5.2,None,7.5,1.8,2.8,None,5.4,6.2] } df = pd.DataFrame(data) # 分组计算max_prev和min_next df['max_prev'] = df.groupby('group_id')['val'].apply(lambda x: x.ffill().shift(1)) df['min_next'] = df.groupby('group_id')['val'].apply(lambda x: x.bfill().shift(-1)) print(df)
代码说明
- max_prev生成逻辑:
- 对每个分组的
val列执行ffill(),将NaN填充为前面最近的非NaN值; - 用
shift(1)将结果整体向下移动一行,这样第一行就变为NaN(符合首尾行边界要求),其余行正好是前序所有行的最大值。
- 对每个分组的
- min_next生成逻辑:
- 对每个分组的
val列执行bfill(),将NaN填充为后面最近的非NaN值; - 用
shift(-1)将结果整体向上移动一行,这样最后一行就变为NaN,其余行正好是后序所有行的最小值。
- 对每个分组的
这种方法完全基于Pandas的向量化操作,避免了循环,处理大数据集时效率很高,同时完美适配连续NaN的场景。
内容的提问来源于stack exchange,提问作者matnor
相关产品推荐
相关产品推荐

