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

月度数据NaN值填充公式失效:如何补全全周期缺失值?

问题:填充Pandas DataFrame全周期缺失值

问题背景

现有如下Pandas DataFrame,其中series1、series2、series3为数值水平列,后缀_yoy的列对应12个月同比增长率:

import pandas as pd
import numpy as np
from numpy import rec,nan

df=pd.DataFrame.from_records(rec.array([
           ('Jan-22', 200., 100., 325.,  nan,  nan,  nan),
           ('Feb-22', 210., 101., 328.,  nan,  nan,  nan),
           ('Mar-22', 212., 102., 329.,  nan,  nan,  nan),
           ('Apr-22', 211., 104., 330.,  nan,  nan,  nan),
           ('May-22', 208., 105., 329.,  nan,  nan,  nan),
           ('Jun-22', 215., 107., 330.,  nan,  nan,  nan),
           ('Jul-22', 219., 108., 321.,  nan,  nan,  nan),
           ('Aug-22', 220., 105., 332.,  nan,  nan,  nan),
           ('Sep-22', 222., 111., 335.,  nan,  nan,  nan),
           ('Oct-22', 223., 115., 338.,  nan,  nan,  nan),
           ('Nov-22', 225., 118., 339.,  nan,  nan,  nan),
           ('Dec-22', 230., 122., 341.,  nan,  nan,  nan),
           ('Jan-23', 235., 124., 342., 17.5, 24. ,  5.2),
           ('Feb-23', 236., 126., 348., 12.4, 24.8,  6.1),
           ('Mar-23', 267., 128., 351., 25.9, 25.5,  6.7),
           ('Apr-23', 288., 130., 326., 36.5, 25. , -1.2),
           ('May-23', 299., 132., 359., 43.8, 25.7,  9.1),
           ('Jun-23', 300., 133., 363., 39.5, 24.3, 10. ),
           ('Jul-23',  nan,  nan,  nan, 12. , 11. ,  5. ),
           ('Aug-23',  nan,  nan,  nan, 11. , 12. ,  4. ),
           ('Sep-23',  nan,  nan,  nan, 10. , 11. ,  3. ),
           ('Oct-23',  nan,  nan,  nan,  9. , 13. ,  2. ),
           ('Nov-23',  nan,  nan,  nan,  8. , 14. ,  1. ),
           ('Dec-23',  nan,  nan,  nan,  7. ,  7. ,  4. ),
           ('Jan-24',  nan,  nan,  nan,  6. ,  8. ,  3. ),
           ('Feb-24',  nan,  nan,  nan,  6. ,  7. ,  1. ),
           ('Mar-24',  nan,  nan,  nan,  5. ,  8. ,  0. ),
           ('Apr-24',  nan,  nan,  nan,  4. ,  9. , -5. ),
           ('May-24',  nan,  nan,  nan,  3. , 10. , -5. ),
           ('Jun-24',  nan,  nan,  nan,  4. ,  5. , -4. ),
           ('Jul-24',  nan,  nan,  nan,  5. ,  4. , -2. ),
           ('Aug-24',  nan,  nan,  nan,  6. ,  2. , -1. ),
           ('Sep-24',  nan,  nan,  nan,  7. ,  2. , -4. ),
           ('Oct-24',  nan,  nan,  nan,  7. ,  2. , -4. ),
           ('Nov-24',  nan,  nan,  nan,  7. ,  2. , -4. ),
           ('Dec-24',  nan,  nan,  nan,  7. ,  2. , -4. )],
          dtype=[('date', 'O'), ('series1', '<f8'), ('series2', '<f8'), ('series3', '<f8'), ('series1_yoy', '<f8'), ('series2_yoy', '<f8'), ('series3_yoy', '<f8')]))

df = df.set_index('date')

需求是从2023年7月开始,用12个月前的数值水平值 × (1 + 同比增长率/100) 填充series1、series2、series3的NaN值。原代码如下:

level_cols = ['series1','series2','series3']
yoy_cols = ['series1_yoy', 'series2_yoy', 'series3_yoy']

for i, x in enumerate(level_cols):
      df[x].fillna(df[x].shift(12) * (1 + df[yoy_cols[i]]/100), inplace=True)

df

但该代码仅填充了2024年6月及之前的缺失值,2024年7月至12月的NaN未被填充。

原因分析

原代码仅执行一次填充操作:

  • 2023年7-12月的缺失值可以通过12个月前(2022年7-12月)的有效值计算得到,因此被填充;
  • 2024年1-6月的缺失值可以通过12个月前(2023年1-6月)的有效值计算得到,因此被填充;
  • 2024年7-12月的缺失值需要12个月前(2023年7-12月)的数值,但原代码计算shift(12)时用的是填充前的原始数据(2023年7-12月当时还是NaN),因此无法完成填充。

需要多次迭代填充,每次迭代都会用上一次填充后的结果来计算后续行的缺失值。

解决方案:使用计数器迭代填充

可以通过循环计数器控制迭代次数,直到所有缺失值被填充,或者根据需要填充的周期数设置固定迭代次数。

方法1:循环直到无缺失值

level_cols = ['series1','series2','series3']
yoy_cols = ['series1_yoy', 'series2_yoy', 'series3_yoy']

# 计数器初始化
iteration_count = 0
max_iterations = 10  # 设置最大迭代次数防止无限循环

while df[level_cols].isna().any().any() and iteration_count < max_iterations:
    for i, x in enumerate(level_cols):
        # 计算填充值:用上一次迭代后的数据做shift
        fill_values = df[x].shift(12) * (1 + df[yoy_cols[i]]/100)
        df[x].fillna(fill_values, inplace=True)
    iteration_count += 1

print(f"完成填充,共迭代{iteration_count}次")
df

方法2:固定迭代次数(针对已知周期)

已知需要填充的周期是2023年7月到2024年12月,共18个月,只需迭代2次即可覆盖所有缺失值:

level_cols = ['series1','series2','series3']
yoy_cols = ['series1_yoy', 'series2_yoy', 'series3_yoy']

# 设置固定迭代次数
for _ in range(2):
    for i, x in enumerate(level_cols):
        fill_values = df[x].shift(12) * (1 + df[yoy_cols[i]]/100)
        df[x].fillna(fill_values, inplace=True)

df

效果说明

  • 第一次迭代:填充2023年7-12月的缺失值;
  • 第二次迭代:2024年7-12月的shift(12)会指向第一次迭代后填充完成的2023年7-12月数据,因此可以顺利计算并填充缺失值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 20:14:51