pandas按国家、产品分组取近3期均值填充$/unit列缺失值
问题背景
现有数据集结构
你持有的DataFrame数据集结构如下:
month country prod sales units cust u/cust $/unit 4/1/2022 FRANCE PROD.A 1715 329 148 2.222973 5.212766 4/1/2022 FRANCE PROD.B 1708 371 156 2.378205 4.603774 4/1/2022 ITALY PROD.A 1636 396 176 2.250000 4.131313 4/1/2022 ITALY PROD.B 1965 308 130 2.369231 6.379870 5/1/2022 FRANCE PROD.A 1623 305 143 2.132867 5.321311 5/1/2022 FRANCE PROD.B 1791 398 140 2.842857 4.500000 5/1/2022 ITALY PROD.A 1753 387 134 2.888060 4.529716 5/1/2022 ITALY PROD.B 1643 394 138 2.855072 4.170051 6/1/2022 FRANCE PROD.A 1600 399 149 2.677852 4.010025 6/1/2022 FRANCE PROD.B 1700 327 132 2.477273 5.198777 6/1/2022 ITALY PROD.A 1619 362 136 2.661765 4.472376 6/1/2022 ITALY PROD.B 1871 369 150 2.460000 5.070461 7/1/2022 FRANCE PROD.A NaN 355 144 2.465278 NaN 7/1/2022 FRANCE PROD.B NaN 320 134 2.388060 NaN 7/1/2022 ITALY PROD.A NaN 377 136 2.772059 NaN 7/1/2022 ITALY PROD.B NaN 363 135 2.688889 NaN
数据集共包含8个字段:month、country、prod、sales、units、cust、u/cust、$/unit,记录了2022年4-7月法国、意大利两个区域PROD.A、PROD.B两款产品的业务指标,其中2022年7月的sales、$/unit字段存在NaN缺失值。
填充需求
对$/unit列做缺失值填充,规则如下:
- 按
country、prod两个维度分组 - 每个缺失值使用同分组下,缺失位置之前最近3条有效
$/unit记录的均值填充 - 示例:法国PROD.A 7月的缺失值,取同分组4、5、6月的
$/unit值(5.21、5.32、4.01)计算均值4.84填充
目前已实现分组前向1位填充的代码,仅能取最近1条有效值填充:
df = df.groupby(['country', 'prod'], as_index=False).apply(lambda group: group.ffill())
需要实现最近3条有效记录均值填充的逻辑。
实现方案
使用pandas滚动窗口计算能力配合分组操作即可实现需求,核心逻辑是对每个分组内的$/unit列做滚动窗口均值计算,窗口大小设为3,计算时仅取当前行之前的有效值,再用计算结果填充对应缺失位。
完整代码
import pandas as pd # 转换月份格式,按分组+月份升序排序,保证时序顺序正确 df['month'] = pd.to_datetime(df['month']) df = df.sort_values(by=['country', 'prod', 'month']).reset_index(drop=True) # 分组计算缺失位置前最近3条有效记录的均值,min_periods=1兼容历史记录不足3条的边界场景 df['fill_value'] = df.groupby(['country', 'prod'])['$/unit'].transform( lambda x: x.shift(1).rolling(window=3, min_periods=1).mean() ) # 仅对缺失位用计算出的均值填充,保留原有非缺失值 df['$/unit'] = df['$/unit'].fillna(df['fill_value']) # 删除临时计算列 df = df.drop(columns=['fill_value'])
代码说明
- 提前排序是核心前提,避免时序混乱导致填充值错误引用未来数据
shift(1)用于排除当前行本身,仅取当前行之前的历史数据计算,符合「缺失值位置之前」的规则要求rolling(window=3, min_periods=1)指定窗口大小为3,当分组内历史有效记录不足3条时,自动用已有的有效记录计算均值,不会产生新的缺失值- 结果校验:法国PROD.A 7月的
$/unit填充值为(5.212766 + 5.321311 + 4.010025)/3 ≈ 4.85,保留两位小数即为示例中提到的4.84,完全匹配需求规则
注意:如果原始数据已经按分组和月份排好序,可以跳过排序步骤,但建议保留该步骤避免异常。
内容的提问来源于stack exchange,提问作者Jose Simon
相关产品推荐
相关产品推荐

