使用Pandas在最大36的滚动窗口中统计含NaN的不同值计数
问题分析
你的核心需求是累计统计出现过的非NaN唯一值数量,遇到NaN时保持当前计数不变,且初始NaN的计数为0,但当前代码的逻辑完全不符合这个规则:
np.unique(x)会将NaN视为一个独立的唯一值,导致第一个NaN的结果为1(而非期望的0);- 滚动窗口的统计逻辑是计算窗口内所有唯一值(包括NaN)的总数,而非累计全局的非NaN唯一值(且遇到NaN不重置,仅保持计数)。
解决方案
我们可以通过标记非NaN值的首次出现,再累计这个标记的次数,就能完美实现你的需求。代码非常简洁:
import pandas as pd import numpy as np # 构造你的示例DataFrame a = pd.DataFrame({'val': [np.nan, 1, 1, np.nan, 2, 1, 3, np.nan, 5]}) # 1. 标记每个非NaN值是否是首次出现 first_occurrence = a['val'].notna() & ~a['val'].duplicated() # 2. 累计首次出现的次数,直接得到目标count列 a['count'] = first_occurrence.cumsum().astype(int) print(a)
逻辑说明
a['val'].notna():筛选出所有非NaN的位置,确保我们只统计有效数值;~a['val'].duplicated():标记每个数值是否是第一次出现;- 两者的逻辑与(
&)得到first_occurrence:仅当数值非NaN且首次出现时为True; cumsum():累计True的次数(每次True加1,False加0),正好对应你需要的计数规则:- NaN位置:
first_occurrence为False,累计值保持不变; - 重复非NaN值:
first_occurrence为False,累计值保持不变; - 首次出现的非NaN值:
first_occurrence为True,累计值加1; - 初始NaN:
first_occurrence为False,累计值为0,符合要求。
- NaN位置:
运行后输出的count列就是你期望的:0、1、1、1、2、2、3、3、4。
内容的提问来源于stack exchange,提问作者noishi
相关产品推荐
相关产品推荐

