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

如何将Pandas的groupby+pct_change(periods=30)语句转换为纯Numpy实现

Pandas groupby pct_change 纯Numpy实现方案

原代码逻辑拆解

原Pandas语句df.groupby(['column'])['new_column'].pct_change(periods=30)的逻辑分为两步:

  • 按column列对数据集做分组,不同分组的计算相互隔离
  • 每个分组内对new_column列计算周期为30的百分比变化,计算公式为 当前值 / 向前偏移30位的数值 - 1,每组长度不足30的部分返回空值

纯Numpy实现代码

import numpy as np

def groupby_pct_change(group_col: np.ndarray, value_col: np.ndarray, periods: int = 30) -> np.ndarray:
    # 按分组列排序,同时保留原始索引用于最终还原顺序
    sorted_idx = np.lexsort((group_col,))
    sorted_groups = group_col[sorted_idx]
    sorted_values = value_col[sorted_idx]
    
    # 定位每个分组的起止边界,兼容数值、字符串类型的分组列
    prepend_val = sorted_groups[0] + 1 if np.issubdtype(sorted_groups.dtype, np.number) else object()
    append_val = sorted_groups[-1] + 1 if np.issubdtype(sorted_groups.dtype, np.number) else object()
    group_boundaries = np.diff(sorted_groups, prepend=prepend_val, append=append_val).nonzero()[0]
    
    # 初始化结果数组,默认值为nan
    result = np.full_like(value_col, np.nan, dtype=np.float64)
    
    # 逐分组计算pct_change
    for start, end in zip(group_boundaries[:-1], group_boundaries[1:]):
        group_length = end - start
        if group_length <= periods:
            continue
        # 计算百分比变化
        pct_vals = (sorted_values[start + periods: end] / sorted_values[start: end - periods]) - 1
        # 赋值到原始索引对应位置
        result[sorted_idx[start + periods: end]] = pct_vals
    
    return result

正确性验证

你可以用以下代码对比Numpy实现和原Pandas代码的输出:

import pandas as pd

# 构造测试数据
df = pd.DataFrame({
    "column": np.random.randint(0, 5, size=2000),
    "new_column": np.random.randn(2000).cumsum() + 10 # 加10避免出现0值导致inf
})

# 原Pandas输出
pd_result = df.groupby("column")["new_column"].pct_change(30).values
# Numpy实现输出
np_result = groupby_pct_change(df["column"].values, df["new_column"].values, periods=30)

# 验证非空位置数值完全一致
print(np.allclose(pd_result[~np.isnan(pd_result)], np_result[~np.isnan(np_result)]))
# 输出为True即说明实现正确

注意事项

  • 如果分组列为字符串/类别类型,不需要额外预处理,上述代码已经做了兼容
  • 如果存在大量极小分组,可将循环逻辑替换为向量化操作提升性能,常规业务场景下上述实现性能足够
  • 若数值列存在0值,除以0会返回inf,和Pandas原生行为一致

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 08:54:04