You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

关键逻辑说明

  1. 迭代填充:通过循环逐次处理每个NaN,每次填充后更新序列,下一次计算会基于已经填充好的值(比如你示例中1,NaN,NaN,4的情况,第一次填充得到1,2.5,NaN,4,第二次用2.5和4的均值填充第二个NaN)。
  2. 边界处理:针对开头/末尾的NaN,我按照你示例中的规则(末尾NaN取前值的一半)实现,如果你需要其他规则(比如直接填充前值),只需要修改对应fill_val的赋值即可。
  3. 数据安全:操作前复制原序列,避免修改原始数据。

内容的提问来源于stack exchange,提问作者Yolao_21

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 22:22:39