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

如何优化循环构建DataFrame的效率,处理大规模SQLite数据集?

性能优化方案

原代码的核心性能瓶颈是两层嵌套循环:外层遍历20万条UNTRMT条目,内层遍历关联的UCBT数据(累计450万次循环),且每次循环中重复执行DataFrame查询、单行数据处理,导致大量不必要的性能损耗。以下是针对性的优化方案:


1. 预处理CRVCRG,建立快速查询映射

CRVCRG仅200行,属于极小数据集,先筛选出tip_dia='DU'的目标数据,再通过索引建立cod_id到对应数据的映射,避免循环中重复执行loc查询:

# 预处理CRVCRG:仅保留DU类型数据,并设置cod_id为索引
crvcrg_du = crvcrg[crvcrg['tip_dia'] == 'DU'].set_index('cod_id')

2. 提前对UCBT按关联键分组

原代码每次遍历UNTRMT时都要筛选对应UCBT数据,改为提前按uni_tr_mt分组,一次分组复用所有查询:

# 对UCBT按uni_tr_mt分组,后续直接调用分组结果
ucbt_grouped = ucbt.groupby('uni_tr_mt')

3. 用分组批量计算替换嵌套循环

将内层遍历UCBT的逻辑改为分组后的批量处理,利用Pandas的apply实现向量化计算,避免逐行循环:

优化后的核心处理逻辑

# 定义分组处理函数,批量计算每个UNTRMT对应的统计值
def process_ucbt_group(group):
    ncons = len(group)
    cc_acc_du = np.zeros(96)
    kWh_du_total = 0

    # 遍历分组内的UCBT数据(此时仅遍历单UNTRMT关联的UCBT,而非全量)
    for _, uc_row in group.iterrows():
        # 直接通过索引快速获取CRVCRG数据,替代原loc查询
        cc_norm_du = crvcrg_du.loc[uc_row['tip_cc']]
        # 调用业务函数计算
        cc_kW_du = nota_tecnica(pd.DataFrame([cc_norm_du]), num_du, uc_row[ene[m]])
        # 累加计算
        cc_acc_du += cc_kW_du.values.flatten()
        kWh_du_total += cc_kW_du.sum() * num_du

    return pd.Series([ncons, kWh_du_total, cc_acc_du], 
                    index=['ncons', 'kWh_du_total', 'cc_acc_du'])

# 批量处理所有分组,得到每个UNTRMT的计算结果
grouped_results = ucbt_grouped.apply(process_ucbt_group).reset_index()

4. 合并结果到UNTRMT,替代手动维护列表

原代码通过aux_list手动收集数据,改为直接合并分组结果到原UNTRMT DataFrame,避免手动管理列表的开销:

# 合并计算结果到原UNTRMT表(假设UNTRMT的主键是uni_tr_mt)
untrmt = untrmt.merge(grouped_results, on='uni_tr_mt', how='left')
# 若原base_du函数有额外逻辑,可在此基础上调整列结构

进阶优化建议

  • 优化nota_tecnica函数:如果该函数是逐行处理的逻辑,尽量改为向量化实现(用numpy操作替代内部循环),这是提升性能的关键环节。
  • 给UCBT建立索引:提前给UCBT的uni_tr_mt列建立索引,进一步加快分组和查询速度:
    ucbt = ucbt.set_index('uni_tr_mt')
    
  • 减少内存占用:对大表UCBT优化数据类型,比如将字符串列转为category类型,数值列用更小的 dtype(如int32替代int64),降低内存开销:
    ucbt['tip_cc'] = ucbt['tip_cc'].astype('category')
    
  • 多进程加速:若单进程仍不够快,可使用swifter库自动将apply转为多进程处理,或用multiprocessing模块拆分分组任务(注意数据传递的开销)。

最终写入SQLite的代码(保留原逻辑)

conn = sqlite3.connect('Updated_DataBase.sqlite')
untrmt.to_sql(name=f'UNTRMT_{system}_{m}', con=conn, if_exists='replace', index=True)
conn.commit()
conn.close()

内容的提问来源于stack exchange,提问作者Luís Henrique Bandéria

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 14:15:02