无需循环的高效求和:基于Pandas优化储能序列计算
Pandas优化求和序列计算(替代低效循环)
需要计算两个由求和操作构成的长序列数据,原Python循环实现效率极低,现采用Pandas的向量化操作进行优化。以下是最小可复现示例(MWE)及原有循环实现:
import numpy as np import pandas as pd T = range(1, 8761) # 全年小时数(共8760小时) T0 = range(6, 8761 + 24, 24) # 存储装置清空的时刻点 e2p = 2 # 能量功率比:存储装置放空所需的最长时长(小时) # 输入数据: # on: 最大存储流入量 # off: 最大存储流出量 df = pd.DataFrame( np.random.randint(0, 100, size=(8760, 2)), index=T, columns=['on', 'off'] ) # 输出列说明: # sum1: 固定清空时刻T0下的最大存储量 # sum2: e2p型存储装置的最大存储量 df['sum1'] = np.nan df['sum2'] = np.nan # 求和场景1 # 逻辑:对于T0中的每个时刻t,[t-23, t]时间段内流入的所有能量,必须在t时刻前全部流出 for t in T0: t0 = max(1, t - 23) t = min(t, 8760) for s in range(t0, t + 1): sum_on = df.loc[t0: s, 'on'].sum() sum_off = df.loc[s + 1: t, 'off'].sum() df.loc[s, 'sum1'] = min(sum_on, sum_off) # 求和场景2 # 逻辑:对于每个时刻t,截止t时刻流入的所有能量,可在t到t+e2p时间段内流出 for t in T: t0 = max(1, t - e2p + 1) tf = min(t + e2p, 8760) sum_on = df.loc[t0: t, 'on'].sum() sum_off = df.loc[t + 1: tf, 'off'].sum() df.loc[t, 'sum2'] = min(sum_on, sum_off)
求和场景1优化方案
利用cumsum()(累加和)替代内层循环的逐次求和,通过反向累加计算后续流出量的总和,大幅提升效率:
# 注:原代码中的VZF应为23,对应原逻辑中的时间段长度 for t in T0: t0 = max(1, t - 23 + 1) t = min(t, 8760) sum_on = df.loc[t0: t, 'on'].cumsum() sum_off = (df.loc[t0: t, 'off'] .iloc[::-1] # 反转序列 .cumsum() # 反向累加 .iloc[::-1] # 恢复原顺序 .shift(periods=-1, fill_value=0)) # 偏移后填充0,对应s+1到t的流出总和 df.loc[t0: t, 'sum1'] = pd.concat([sum_on, sum_off], axis=1).min(axis=1)
求和场景2优化方案
利用rolling().sum()(滚动求和)实现窗口内的累加,结合序列反转实现反向窗口求和,完全替代循环操作:
# 计算截止t时刻,过去e2p小时内的流入总和 sum_on = df['on'].rolling(window=e2p, min_periods=1).sum() # 计算t时刻之后e2p小时内的流出总和:先偏移1位(对应t+1开始),再反转后滚动求和,最后恢复顺序 sum_off = (df['off'] .shift(periods=-1, fill_value=0) .iloc[::-1] .rolling(window=e2p, min_periods=1) .sum() .iloc[::-1]) df['sum2'] = pd.concat([sum_on, sum_off], axis=1).min(axis=1)
内容的提问来源于stack exchange,提问作者clueless
相关产品推荐
相关产品推荐

