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

使用Pandas实现时间序列前置NaN的观测值分配填充

解决时间序列累计值分配到前置NaN的问题

我完全懂你的需求——要把每个非NaN的累计总量,平均分配到它之前连续的NaN区间(包括自身所在时间步),这种特殊逻辑确实没法用bfill或者普通interpolate直接搞定,得自定义逻辑来实现。下面是针对Pandas的具体解决方案:

核心思路拆解

  1. 给每个需要分配的区间打「分组标签」:把每个非NaN值和它前面的连续NaN划进同一个组
  2. 统计每个组的关键信息:组内的时间步数、对应的累计总量
  3. 计算单步分配值:用累计总量除以组内步数,给组内每个时间步赋值
  4. 保留末尾无对应累计值的NaN:如果最后几个时间步都是NaN,保持原状态不变

代码实现(附示例数据)

假设你的DataFrame命名为df,包含Timestep和Value两列,代码如下:

import pandas as pd
import numpy as np

# 加载你的示例数据
data = {
    'Timestep': [1,2,3,4,5,6,7,8,9,10],
    'Value': [10, np.nan, np.nan, 9, np.nan, np.nan, np.nan, 16, np.nan, np.nan]
}
df = pd.DataFrame(data)

# 1. 创建分组标签:遇到非NaN值就新建一个组,连续NaN自动归到下一个非NaN的组
df['group'] = df['Value'].notna().cumsum()

# 2. 统计每个组的累计值和组内步数
group_info = df.groupby('group').agg(
    total=('Value', 'last'),  # 取组内唯一的非NaN值(累计总量)
    step_count=('Value', 'count')  # 组内包含的时间步数
)

# 3. 合并统计信息,计算每个时间步的分配值
df = df.merge(group_info, on='group', how='left')
df['Value'] = df['total'] / df['step_count']

# 4. 处理末尾无累计值的NaN组
df.loc[df['total'].isna(), 'Value'] = np.nan

# 清理临时辅助列
df = df.drop(['group', 'total', 'step_count'], axis=1)

print(df)

输出结果

运行后会得到你期望的格式:

Timestep  Value
0         1   10.0
1         2    3.0
2         3    3.0
3         4    3.0
4         5    4.0
5         6    4.0
6         7    4.0
7         8    4.0
8         9    NaN
9        10    NaN

逻辑细节解释

  • df['Value'].notna().cumsum():每碰到一个非NaN值,分组ID就+1,这样Timestep2-4会被归到同一个组(对应累计值9),Timestep5-8归到同一个组(对应累计值16)
  • 分组统计时,total取组内最后一个值(也就是那个唯一的非NaN累计值),step_count是组内的总步数
  • 用累计值除以步数,就得到每个时间步的平均分配值
  • 最后一组(Timestep9-10)因为没有对应的非NaN累计值,total为NaN,所以保持Value为NaN,完全符合你的要求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 06:38:57