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

Pandas优化迭代:大DataFrame序列占比计算提速方案咨询

Pandas大DataFrame提速方案:替换逐行循环为向量化操作

你的代码处理85万行耗时10秒的核心原因是逐行循环+df.at逐行赋值——df.at每次操作都会触发DataFrame内部的索引更新和数据校验,85万次调用的累积开销极其高昂。以下是完全基于Pandas向量化操作的优化方案,能将耗时压缩到毫秒级。

优化思路

利用Pandas的**游程编码(Run-Length Encoding)**将连续相同的Phase值分组,通过分组统计和高效匹配计算目标占比,最后用向量化填充完成列赋值,全程避免显式Python循环。

完整优化代码

import pandas as pd
import time

t1 = time.time()

# 1. 生成连续相同Phase的分组ID(游程编码)
df['group_id'] = df['Phase'].ne(df['Phase'].shift()).cumsum()

# 2. 统计每个分组的核心信息:Phase值、长度、最后一行索引
group_info = df.groupby('group_id').agg(
    phase=('Phase', 'first'),
    length=('Phase', 'count'),
    end_idx=('Phase', 'last')
).reset_index()

# 3. 筛选所有Phase=1的分组,匹配其最近的Phase=0分组并计算占比
groups_0 = group_info[group_info['phase'] == 0][['group_id', 'length']].rename(columns={'length': 'len_0'})
groups_1 = group_info[group_info['phase'] == 1].copy()
# 用merge_asof高效匹配最近的前置0分组
groups_1 = pd.merge_asof(groups_1, groups_0, on='group_id', direction='backward')

# 计算占比:仅当存在有效0分组时计算,否则保持0
groups_1['ratio'] = groups_1.apply(
    lambda x: (x['len_0'] / (x['len_0'] + x['length'])) * 100 if pd.notna(x['len_0']) else 0,
    axis=1
)

# 4. 初始化并填充Ratio列
df['Ratio'] = 0
# 在1分组结束的位置设置对应占比
df.loc[groups_1['end_idx'], 'Ratio'] = groups_1['ratio'].values
# 向前填充:后续行自动继承最近一次更新的占比
df['Ratio'] = df['Ratio'].ffill()

# 清理中间列(可选)
df.drop(columns='group_id', inplace=True)

print("Elapsed: %.2f seconds" % (time.time() - t1))

关键优化点说明

  • 游程编码分组:用df['Phase'].ne(df['Phase'].shift()).cumsum()快速生成连续相同值的分组ID,将85万行数据压缩为远更少的分组数;
  • 高效匹配:pd.merge_asof是专门用于有序数据的最近邻匹配方法,比手动循环查找前置分组快几个数量级;
  • 向量化填充:ffill()(向前填充)是Pandas内部优化的向量化操作,完全替代逐行赋值的低效逻辑;
  • 避免逐行操作:所有核心计算都基于分组统计和批量赋值,彻底消除Python循环的开销。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 20:40:10