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

如何在Pandas中按单词分组计算增量与百分比变化并优化性能

高效计算分组时序差值与百分比变化(300万+数据集优化)

问题背景

现有数据集df结构如下:

datewordtotaltop
14/10/2023python525
15/10/2023python549
16/10/2023R522
17/10/2023R121
18/10/2023R451

需要新增两列:

  • delta_top:同一word下当前日期与上一日期top列的差值,无前置数据时为NA
  • delta_total:同一word下当前日期相对上一日期total列的增减百分比,无前置数据时为NA

期望输出:

datewordtotaltopdelta_topdelta_total
14/10/2023python525NANA
15/10/2023python54940.037037037
16/10/2023R522NANA
17/10/2023R1211-0.769230769
18/10/2023R45102.75

用户原尝试代码(针对300万+数据运行极慢):

df = (
    df.assign(date=pd.to_datetime(df['date'], format='%d/%m/%Y'))
      .sort_values(by=['word', 'date'])
      .assign(delta_top=lambda x: x['top'] - x.groupby('word')['top'].shift(1),
              delta_total=lambda x: ((x['total'] - x.groupby('word')['total'].shift(1)) / x.groupby('word')['total'].shift(1)).fillna('NA'))

优化方案

原代码性能瓶颈在于重复执行groupby('word')操作,每次assign中的lambda都会重新分组,对超大数据集产生大量冗余计算。优化核心是减少重复分组,一次性完成移位值计算。

优化后代码

# 先转换日期格式并按分组+日期排序,确保时序逻辑正确
df['date'] = pd.to_datetime(df['date'], format='%d/%m/%Y')
df.sort_values(by=['word', 'date'], inplace=True)

# 仅执行一次分组,批量计算移位后的值
grouped = df.groupby('word')
df['top_shifted'] = grouped['top'].shift(1)
df['total_shifted'] = grouped['total'].shift(1)

# 计算目标列
df['delta_top'] = df['top'] - df['top_shifted']
df['delta_total'] = (df['total'] - df['total_shifted']) / df['total_shifted']

# 清理临时列,将NaN替换为标准缺失值pd.NA(替代字符串'NA'更符合pandas数据规范)
df.drop(columns=['top_shifted', 'total_shifted'], inplace=True)
df[['delta_top', 'delta_total']] = df[['delta_top', 'delta_total']].fillna(pd.NA)

额外性能优化建议

  1. 用diff()简化差值计算:delta_top可直接用grouped['top'].diff()替代x - x.shift(1),代码更简洁且性能一致:
    df['delta_top'] = grouped['top'].diff()
    
  2. 内存优化:若数据集内存占用过高,可将total、top等列转换为更紧凑的数值类型(如int32),减少内存开销
  3. 避免链式写法的隐性重复计算:链式写法虽优雅,但大数据场景下易隐藏重复分组/计算,拆分步骤更利于性能管控

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 00:13:22