You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

新手求助:优化DataFrame滚动求和计算月度最大半小时电力负荷代码

优化电力负荷数据的月度滚动半小时最大需求计算

我完全懂你现在的困扰——100个用户、每个超10万行的数据集,原代码单用户就要跑36分钟,这效率确实没法接受。咱们先拆解原代码里拖慢速度的核心问题,再一步步给出高效的优化方案。

原代码的性能瓶颈

  • 重复的数据查询开销:最内层循环里反复执行df_input[filename].loc[df_input[filename]['Date_conv']==m_o_y],每次都要重新筛选数据,这是巨大的性能浪费
  • Python原生循环的低效:用for循环逐行计算窗口求和,完全没利用Pandas的向量化运算能力,这是处理大数据时的典型低效操作
  • 错误的结果拼接方式:直接给df_m_hh_max的列赋值会导致数据覆盖,最后可能只保留最后一条记录,而且这种方式本身也不高效

优化方案:用Pandas向量化+窗口函数重构

下面是重构后的代码,完全基于Pandas的内置优化函数,效率能提升几个数量级:

import pandas as pd

def monthly_hh_maximum(df_input, filenames):
    # 提前初始化结果DataFrame,指定列类型更高效
    df_m_hh_max = pd.DataFrame(columns=['filename', 'm_o_y', 'm_max'], dtype='float64')
    
    for filename in filenames:
        print(f"Processing {filename}...")
        # 一次性取出当前用户的所有数据,避免重复查询
        user_df = df_input[filename].copy()
        
        # 1. 用滚动窗口计算所有连续6条记录的求和(30分钟负荷)
        # rolling是Pandas底层优化的向量化操作,比Python循环快几十倍
        user_df['30min_sum'] = user_df['load power (kW)'].rolling(window=6, min_periods=6).sum()
        
        # 2. 按月份分组,直接提取每个月的滚动求和最大值
        monthly_max = user_df.groupby('Date_conv')['30min_sum'].max().reset_index()
        
        # 3. 添加用户标识,合并到结果集
        monthly_max['filename'] = filename
        df_m_hh_max = pd.concat(
            [df_m_hh_max, monthly_max.rename(columns={'Date_conv': 'm_o_y', '30min_sum': 'm_max'})],
            ignore_index=True
        )
    
    return df_m_hh_max

优化点详解

  1. 避免重复数据筛选:每个用户的数据只取出一次,后续所有操作都基于这个本地DataFrame,省去了反复loc查询的巨大开销
  2. 向量化滚动计算:rolling().sum()是Pandas底层用C实现的向量化操作,一次性计算所有窗口的求和值,比Python原生循环效率提升百倍以上
  3. 分组聚合取最大值:groupby().max()直接按月份分组提取最大值,替代了内层循环的逐次比较逻辑,代码更简洁且效率更高
  4. 正确的结果拼接:用pd.concat批量合并每个用户的月度结果,避免了原代码中列赋值导致的数据覆盖问题

额外性能升级建议

  • 日期格式优化:如果Date_conv还不是标准日期类型,提前转换为datetime后提取月份(比如user_df['Date_conv'] = user_df['datetime_col'].dt.to_period('M')),分组会更稳定
  • 内存优化:如果精度允许,把load power (kW)列转换为float32类型,减少内存占用,能进一步提升运算速度
  • 并行处理:如果你的机器有多核心CPU,可以用多进程并行处理不同用户的数据,100个用户的处理时间能压缩到几十分钟内。举个简单示例:
from multiprocessing import Pool

def process_single_user(filename):
    user_df = df_input[filename].copy()
    user_df['30min_sum'] = user_df['load power (kW)'].rolling(window=6, min_periods=6).sum()
    monthly_max = user_df.groupby('Date_conv')['30min_sum'].max().reset_index()
    monthly_max['filename'] = filename
    return monthly_max.rename(columns={'Date_conv': 'm_o_y', '30min_sum': 'm_max'})

if __name__ == '__main__':
    # 根据你的CPU核心数调整processes参数
    with Pool(processes=4) as pool:
        results = pool.map(process_single_user, filenames)
    df_m_hh_max = pd.concat(results, ignore_index=True)

这样调整后,原本需要几天的计算任务,应该能在几十分钟内完成。

内容的提问来源于stack exchange,提问作者Zeba Anjum

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:44:08