Pandas带Datetime Index多列滚动窗口传递DataFrame至自定义函数方法
你遇到的问题本质是 pandas的rolling().apply()默认会逐列处理DataFrame——每一列的滚动窗口会被单独作为Series传入你的自定义函数,所以extract_features只能拿到单列数据,而非包含data_1和data_2的完整窗口DataFrame。
下面是一个简单且高效的调整方案,让你的自定义函数能接收包含所有列的窗口DataFrame:
步骤1:修改特征收集类,保存原DataFrame引用
我们需要在FeatureCollector中保存原始DataFrame的引用,这样就能通过窗口的时间索引,提取出对应时间范围的完整窗口数据:
import pandas as pd class FeatureCollector: def __init__(self, original_df): self.feature_dicts = [] self.original_df = original_df # 保存原DataFrame,用于后续提取完整窗口 def collect(self, window_series): # 利用窗口Series的索引,从原DataFrame中取出包含所有列的窗口DataFrame window_df = self.original_df.loc[window_series.index] # 调用你的特征提取函数,传入完整窗口 self.feature_dicts.append(extract_features(window_df)) # 返回任意值即可(apply需要返回与输入窗口长度匹配的结果,这里返回1不影响特征收集) return 1 def extract_features(window_df): ans = {} # 这里可以自由使用window_df的所有列计算特征 ans['data_1_avg'] = window_df['data_1'].mean() ans['data_2_latest'] = window_df['data_2'].dropna().iloc[-1] if not window_df['data_2'].isna().all() else None # 添加你的自定义特征逻辑 return ans
步骤2:调整滚动窗口的调用方式
注意:只需要对DataFrame中的任意一列执行apply,因为所有列的滚动窗口时间索引是完全一致的,这样可以避免逐列重复收集特征:
# 假设你的原始DataFrame是my_df,已设置DatetimeIndex collector = FeatureCollector(my_df) # 选择任意一列(比如data_1)执行滚动窗口操作 my_df['data_1'].rolling( window=pd.Timedelta(seconds=100), min_periods=10 ).apply(collector.collect, raw=False) # 最终获取所有窗口的特征 features = collector.feature_dicts
为什么这个方法可行?
滚动窗口传入的window_series(哪怕是单列的)包含了当前窗口的全部时间索引,我们通过original_df.loc[window_series.index]就能精准提取出该时间范围内的所有列数据,得到完整的窗口DataFrame。而且只对一列调用apply,保证每个窗口只会触发一次特征收集,不会产生重复数据。
额外提示
- 确保你的原始DataFrame的索引是唯一的DatetimeIndex,否则
loc可能返回重复数据 - 如果数据量极大,这种方法的效率不如直接处理ndarray,但对于绝大多数时间序列场景,它的可读性和易用性都更优
内容的提问来源于stack exchange,提问作者Андрей Подопрос
相关产品推荐
相关产品推荐

