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

如何基于前序预测与实际值关联填充Pandas DataFrame缺失值

基于实际值与预测值的差值规律填充Pandas缺失值

问题

如何基于已有前序行的商品预测值与另一列商品实际值的差值规律,填充Pandas DataFrame中的缺失值?

背景详情

我有一个10列40行的Pandas DataFrame,包含以下列:

  • Date:小时级时间戳;
  • Actual:商品的实际观测值,无缺失;
  • time_from_actual_1至time_from_actual_8:商品的超前预测值,仅每日首行(索引0、24)有初始值,其余23行均为NaN。

填充规则

要求time_from_actual_*列的缺失值遵循前一行预测值与实际值的差值保持恒定的规律,即:

当前行预测值 = 当前行实际值 + (前一行预测值 - 前一行实际值)

现有实现(嵌套循环)

我已通过嵌套for循环实现需求,但希望得到更高效、优雅的方案,以下是完整样本数据与代码:

# 导入库
import pandas as pd
import numpy as np

# 设置随机种子
np.random.seed(42)

# 样本数据
data = {
    'Date': pd.date_range(start='2023-01-01', periods=40, freq='H'),
    'Actual': [100, 99.72, 101.02, 104.06, 103.60, 103.13, 106.29, 107.82, 106.88, 107.97,
               107.04, 106.11, 106.59, 102.77, 99.32, 98.19, 96.17, 96.80, 94.98, 92.15,
               95.09, 94.63, 94.77, 91.92, 90.83, 91.05, 88.75, 89.50, 88.30, 87.72,
               86.51, 90.22, 90.19, 88.08, 89.72, 87.28, 87.70, 83.78, 81.12, 131.52],
    'time_from_actual_1': [97] + [np.nan]*23 + [90] + [np.nan]*15,
    'time_from_actual_2': [99] + [np.nan]*23 + [89] + [np.nan]*15,
    'time_from_actual_3': [98] + [np.nan]*23 + [88] + [np.nan]*15,
    'time_from_actual_4': [97] + [np.nan]*23 + [87] + [np.nan]*15,
    'time_from_actual_5': [96] + [np.nan]*23 + [86] + [np.nan]*15,
    'time_from_actual_6': [95] + [np.nan]*23 + [85] + [np.nan]*15,
    'time_from_actual_7': [94] + [np.nan]*23 + [84] + [np.nan]*15,
    'time_from_actual_8': [93] + [np.nan]*23 + [83] + [np.nan]*15,
}

# 创建DataFrame
df = pd.DataFrame(data)

# 复制原DataFrame用于参照原始缺失值
original_df = df.copy()

# 获取所有预测列
time_cols = [col for col in df.columns if col.startswith('time_from_actual')]

# 嵌套循环填充缺失值
for col in time_cols:
    for i in range(1, len(df)):
        if pd.isnull(df.loc[i, col]):
            j = i
            while j < len(df) and pd.isnull(original_df.loc[j, col]):
                previous_actual = df.loc[j - 1, 'Actual']
                previous_time = df.loc[j - 1, col]
                current_actual = df.loc[j, 'Actual']
                difference = previous_time - previous_actual
                df.loc[j, col] = current_actual + difference
                j += 1

优化方案:向量化操作实现

观察填充规则可以发现:预测值与实际值的差值在连续缺失段内是恒定的(即预测值 - 实际值 = 常数)。基于这个规律,我们可以用Pandas的向量化操作替代循环,大幅提升效率:

import pandas as pd
import numpy as np

np.random.seed(42)

# 样本数据(同前)
data = {
    'Date': pd.date_range(start='2023-01-01', periods=40, freq='H'),
    'Actual': [100, 99.72, 101.02, 104.06, 103.60, 103.13, 106.29, 107.82, 106.88, 107.97,
               107.04, 106.11, 106.59, 102.77, 99.32, 98.19, 96.17, 96.80, 94.98, 92.15,
               95.09, 94.63, 94.77, 91.92, 90.83, 91.05, 88.75, 89.50, 88.30, 87.72,
               86.51, 90.22, 90.19, 88.08, 89.72, 87.28, 87.70, 83.78, 81.12, 131.52],
    'time_from_actual_1': [97] + [np.nan]*23 + [90] + [np.nan]*15,
    'time_from_actual_2': [99] + [np.nan]*23 + [89] + [np.nan]*15,
    'time_from_actual_3': [98] + [np.nan]*23 + [88] + [np.nan]*15,
    'time_from_actual_4': [97] + [np.nan]*23 + [87] + [np.nan]*15,
    'time_from_actual_5': [96] + [np.nan]*23 + [86] + [np.nan]*15,
    'time_from_actual_6': [95] + [np.nan]*23 + [85] + [np.nan]*15,
    'time_from_actual_7': [94] + [np.nan]*23 + [84] + [np.nan]*15,
    'time_from_actual_8': [93] + [np.nan]*23 + [83] + [np.nan]*15,
}

df = pd.DataFrame(data)

# 获取所有预测列
time_cols = [col for col in df.columns if col.startswith('time_from_actual')]

# 批量填充缺失值
for col in time_cols:
    # 计算预测值与实际值的差值
    diff = df[col] - df['Actual']
    # 向前填充差值(保持连续段内差值恒定)
    diff_filled = diff.ffill()
    # 反向计算得到填充后的预测值
    df[col] = df['Actual'] + diff_filled

方案优势

  1. 效率提升:向量化操作避免了Python层循环,在大数据集下性能远超嵌套循环;
  2. 代码简洁:逻辑清晰直观,行数更少,易于维护和调试;
  3. 结果一致:完全符合原填充规则,输出结果与嵌套循环完全相同。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 14:54:52