基于时间索引的NaN前向填充及1小时窗口交易累计统计问询
解决两个Pandas时间序列统计问题
一、基于时间索引实现NaN的前向填充
这个其实很简单,Pandas专门提供了前向填充的方法,直接用ffill()(或者等价的fillna(method='ffill'))就行,前提是你的时间索引已经是Datetime类型的有序索引。
操作步骤:
- 先确保时间列是Datetime类型(如果还不是的话):
df['timestamp'] = pd.to_datetime(df['timestamp'])
- 设置时间列为索引(如果没设置的话):
df = df.set_index('timestamp')
- 执行前向填充:
# 填充整个DataFrame的所有NaN df_filled = df.ffill() # 或者只填充特定列,比如某一列叫value df['value'] = df['value'].ffill()
如果需要限制填充的最大时间间隔(比如只填充1小时内的缺失值),可以结合时间偏移和limit参数,但普通场景用上面的方法就足够了。
二、高效实现按Id分组的过去1小时各交易类型累计统计
你之前用groupby(['Id', 'tradeType'])+rolling('60T')出现NaN,是因为先过滤了特定交易类型,导致其他行没有数据;而遍历行的方法效率低,是因为循环逐行处理完全没用到Pandas矢量化操作的优势。
下面给你一个高效的矢量化方案,数据量越大,对比遍历的效率提升越明显:
核心思路
先把交易类型转成哑变量(0/1),然后按Id分组做1小时滚动求和,直接得到每个时间点过去1小时内各交易类型的累计数量,全程没有NaN,也不需要循环。
完整代码示例
import pandas as pd from datetime import timedelta # 1. 预处理:确保时间列是Datetime类型 df['timestamp'] = pd.to_datetime(df['timestamp']) # 设置时间列为索引(方便后续滚动操作) df = df.set_index('timestamp') # 2. 生成交易类型的哑变量:每个类型对应一列,存在该类型则为1,否则为0 dummies = pd.get_dummies(df['tradeType'], prefix='count') # 列名会变成count_B、count_W等 # 把哑变量和原表的Id列合并 df_with_dummies = pd.concat([df[['Id']], dummies], axis=1) # 3. 按Id分组,做1小时滚动求和 # rolling('60T')表示窗口为过去60分钟,sum()计算累计数量 rolling_counts = df_with_dummies.groupby('Id').rolling('60T').sum() # 调整索引:去掉groupby后的Id层级,和原表索引对齐 rolling_counts = rolling_counts.reset_index(level=0, drop=True) # 4. 合并回原表,得到最终结果 df_final = df.join(rolling_counts)
关键说明
- 为什么这个方法没有NaN?因为哑变量对不存在的交易类型会填充0,滚动求和时即使过去1小时内没有该类型,结果也是0,完全符合统计需求。
- 如果需要排除当前行的统计(比如只算当前时间之前1小时的交易,不含当前行),可以给rolling加
closed='left'参数:rolling_counts = df_with_dummies.groupby('Id').rolling('60T', closed='left').sum() - 这个方法是纯矢量化操作,效率比遍历行高几个数量级,几万甚至几十万行数据都能秒级处理。
内容的提问来源于stack exchange,提问作者김정민
相关产品推荐
相关产品推荐

