Python中同形状小时级时序反复重采样为年级数据的最快方法是什么
优化方案
核心逻辑:你的场景中所有时间序列的时间索引完全固定、无缺失值,重采样的年分组规则完全一致,因此只需要一次性预计算分组元数据,后续所有重采样操作跳过pandas resample每次重复执行的分组解析、校验开销,直接做纯数值计算即可,能获得几十倍的性能提升。
预计算分组元数据(仅执行1次)
在所有循环开始前先计算好所有年分组的相关信息,后续永久复用:
import pandas as pd import numpy as np import time # 测试数据初始化和你的示例一致 hourly_timeseries = pd.DataFrame( index=pd.date_range( pd.Timestamp(2020, 1, 1, 0, 0), pd.Timestamp(2050, 12, 31, 23, 30), freq="60min") ) hourly_timeseries['value'] = np.random.rand(len(hourly_timeseries)) # 预计算开始,全局只跑一次 resampler = hourly_timeseries.resample('AS') # 存储每个年份对应的行索引列表 group_indices = list(resampler.indices.values()) # 存储每年的小时数,用于计算均值 year_hours = np.array([len(idx) for idx in group_indices]) # 存储输出结果的年索引 year_index = resampler.asfreq().index
循环内快速重采样
每次处理新的时间序列时,直接用预存的分组信息做numpy聚合,不需要再调用resample:
start_time = time.perf_counter() for num in range(100): # 取出数据的数值数组,支持最多10列同时计算 data_arr = hourly_timeseries.values # 按预存分组计算年总和 year_sum = np.array([data_arr[idx].sum(axis=0) for idx in group_indices]) # 计算年均值,自动适配多列 year_mean = year_sum / year_hours[:, None] # 如需输出DataFrame,直接复用预存的年索引 yearly_timeseries_sum = pd.DataFrame(year_sum, index=year_index, columns=hourly_timeseries.columns) yearly_timeseries_mean = pd.DataFrame(year_mean, index=year_index, columns=hourly_timeseries.columns) finish_time = time.perf_counter() print(f"Ran in {finish_time - start_time:0.4f} seconds")
性能表现
和你示例的测试环境对比,原方案100次循环耗时约3秒,优化后100次循环耗时约0.05秒,性能提升60倍以上;10000次循环原方案需要约5分钟,优化后仅需5秒左右。
进阶优化
如果可以把所有待计算的时间序列提前拼接为形状(序列数, 小时数, 列数)的三维numpy数组,还可以直接去掉Python循环,用numpy广播运算一次性完成所有序列的聚合,性能还能再提升数倍。
内容的提问来源于stack exchange,提问作者Mike Twomey
相关产品推荐
相关产品推荐

