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

如何按指定公式填充Pandas DataFrame中的NaN中间值?

Pandas DataFrame按自定义递推公式填充NaN值

问题说明

现有DataFrame结构如下:

value
30
NaN
NaN
25
NaN
20
NaN
NaN
NaN
NaN
15
...

需要按以下自定义递推公式填充NaN:
当前填充值 = 前一个有效值(或已填充值) - ((前一个值 - 后一个有效值) / 剩余待填充的NaN数量)

示例计算:

  • 第一个NaN:30 - (30-25)/2 = 27.5
  • 第二个NaN:27.5 - (27.5-25)/1 = 25

期望得到的结果:

valueexpected value
3030
NaN27.5
NaN25
2525
NaN20
2020
NaN18.75
NaN17.5
NaN16.25
NaN15
1515
......

解决方案

通过标记锚点分组+递推计算的方式实现:

import pandas as pd
import numpy as np

# 构造示例DataFrame
df = pd.DataFrame({
    'value': [30, np.nan, np.nan, 25, np.nan, 20, np.nan, np.nan, np.nan, np.nan, 15]
})

# 给每个连续NaN区间标记分组ID
df['anchor_group'] = df['value'].notna().cumsum()
# 提取所有非NaN锚点的位置和数值
anchor_points = df[df['value'].notna()].reset_index()

# 遍历每对相邻锚点,填充中间的NaN
for i in range(len(anchor_points)-1):
    start_idx = anchor_points.loc[i, 'index']
    end_idx = anchor_points.loc[i+1, 'index']
    start_val = anchor_points.loc[i, 'value']
    end_val = anchor_points.loc[i+1, 'value']
    nan_count = end_idx - start_idx - 1
    
    if nan_count <= 0:
        continue
    
    # 递推生成填充序列
    fill_seq = [start_val]
    current_val = start_val
    for _ in range(nan_count):
        remaining_nans = nan_count - len(fill_seq) + 1
        step = (current_val - end_val) / remaining_nans
        current_val -= step
        fill_seq.append(current_val)
    
    # 将填充值写入DataFrame
    df.loc[start_idx+1:end_idx-1, 'value'] = fill_seq[1:]

# 移除临时分组列
df.drop('anchor_group', axis=1, inplace=True)
print(df)

代码逻辑解析

  1. 锚点分组:用notna().cumsum()给每段连续NaN区间分配唯一分组ID,确保每个区间对应前后两个有效锚点。
  2. 锚点提取:筛选出所有非NaN值的位置和数值,作为填充的起始和终止参照。
  3. 递推填充:针对每段NaN区间,按照自定义公式逐步计算每个位置的填充值,每一步都用上一步的结果更新当前值,完全匹配需求中的递推逻辑。

运行结果

执行代码后,df['value']将得到与期望列一致的填充结果:

indexvalue
030.00
127.50
225.00
325.00
420.00
520.00
618.75
717.50
816.25
915.00
1015.00

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 14:25:47