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

Pandas稀疏DataFrame向前填充NaN的高效实现方法

加速稀疏DataFrame的递归填充:前一个非NaN值减1

你的需求本质是向前填充后,每个位置的值等于最近的前一个非NaN值减去它与该非NaN值之间的行数差,原来的循环方法因为多次调用fillna导致效率低下,我们可以用向量化操作来实现,速度和ffill相当。

核心思路

  1. 先用ffill()获取每列的前向填充值,得到每个位置对应的最近非NaN基准值;
  2. 计算每个位置到最近前一个非NaN值的行数偏移量(即从基准值开始往后数的第几个位置);
  3. 用基准值减去偏移量,得到最终填充结果。

实现代码

import pandas as pd
import numpy as np

# 初始化示例DataFrame
df = pd.DataFrame(np.nan, index=range(10), columns=['A', 'B', 'C'])
df.loc[(0,'A')] = 6
df.loc[(3,'A')] = 8
df.loc[(4,'B')] = 2

# 核心填充逻辑
mask = df.notna()
ffilled = df.ffill()
# 生成分组ID:每个非NaN值开始一个新分组
group_ids = mask.cumsum()
# 计算每个组内的偏移量(从0开始计数)
offsets = group_ids.apply(lambda col: col.groupby(col).cumcount())
# 计算最终结果
result_df = ffilled - offsets

print(result_df)

运行后输出和你示例中的填充结果完全一致:

A    B   C
0  6.0  NaN NaN
1  5.0  NaN NaN
2  4.0  NaN NaN
3  8.0  NaN NaN
4  7.0  2.0 NaN
5  6.0  1.0 NaN
6  5.0  0.0 NaN
7  4.0 -1.0 NaN
8  3.0 -2.0 NaN
9  2.0 -3.0 NaN

性能优势

  • 原来的循环方法需要遍历每一行,每次调用fillna都会产生中间DataFrame,时间复杂度是O(n²)(n为行数);
  • 向量化方法只需要几次整体操作,时间复杂度是O(n),和ffill的效率几乎一致,对于大尺寸DataFrame速度提升非常明显。

补充说明

  • 对于全NaN的列(比如示例中的列C),结果会保持全NaN,符合预期;
  • 如果DataFrame的行不是连续整数索引,这个方法依然有效,因为cumcount是基于分组内的顺序计算偏移量的。

内容的提问来源于stack exchange,提问作者Giovanni De Gaetano

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:23:14