如何在Pandas中动态替换DataFrame的NaN值(基于相邻非NaN值逐次均值填充)
实现Pandas中NaN值的动态逐次均值填充
我明白你要的是迭代式的动态填充——每次只填充一个NaN,用它当前前后最近的非NaN值(包括已经填充好的值)计算均值,而不是一次性算出所有填充值。常规的ffill()+bfill()/interpolate()确实做不到这点,因为它们都是基于原始数据一次性生成结果。
下面是完全符合你需求的实现方案:
完整代码示例
import pandas as pd import numpy as np def dynamic_mean_fill(series): # 复制原序列,避免修改原始数据 filled_series = series.copy().reset_index(drop=True) has_nan = filled_series.isna().any() while has_nan: # 找到第一个未填充的NaN位置 first_nan_idx = filled_series.isna().idxmax() # 获取该位置前最后一个非NaN值 prev_valid = filled_series[:first_nan_idx].dropna() prev_val = prev_valid.iloc[-1] if not prev_valid.empty else None # 获取该位置后第一个非NaN值 next_valid = filled_series[first_nan_idx+1:].dropna() next_val = next_valid.iloc[0] if not next_valid.empty else None # 按规则计算填充值 if prev_val is not None and next_val is not None: fill_val = (prev_val + next_val) / 2 elif prev_val is not None: # 处理末尾无后续值的情况(匹配你示例中a列第9行的规则) fill_val = prev_val / 2 elif next_val is not None: # 处理开头无前驱值的情况,可按需调整规则 fill_val = next_val / 2 else: # 全NaN的极端情况,保持NaN fill_val = np.nan # 填充当前NaN filled_series.iloc[first_nan_idx] = fill_val # 更新NaN状态,继续循环直到全部填充完成 has_nan = filled_series.isna().any() return filled_series # 初始化你的DataFrame df = pd.DataFrame({ 'a':[1,2,np.nan,1,np.nan,np.nan,4,2,3,np.nan], 'b':[4,2,3,np.nan,np.nan,1,5,np.nan,5,8] }) # 对每一列应用动态填充 filled_df = df.apply(dynamic_mean_fill) # 查看结果(保留两位小数和你示例一致) print(filled_df.round(2))
输出结果
a b 0 1.00 4.0 1 2.00 2.0 2 1.50 3.0 3 1.00 2.0 4 2.50 1.5 5 3.25 1.0 6 4.00 5.0 7 2.00 5.0 8 3.00 5.0 9 1.50 8.0
关键逻辑说明
- 迭代填充:通过循环逐次处理每个NaN,每次填充后更新序列,下一次计算会基于已经填充好的值(比如你示例中
1,NaN,NaN,4的情况,第一次填充得到1,2.5,NaN,4,第二次用2.5和4的均值填充第二个NaN)。 - 边界处理:针对开头/末尾的NaN,我按照你示例中的规则(末尾NaN取前值的一半)实现,如果你需要其他规则(比如直接填充前值),只需要修改对应
fill_val的赋值即可。 - 数据安全:操作前复制原序列,避免修改原始数据。
内容的提问来源于stack exchange,提问作者Yolao_21
相关产品推荐
相关产品推荐

