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

如何高效遍历Pandas DataFrame并计算同ID历史行均值

解决Pandas中按ID计算上方行均值的高效方法

首先,咱们先分析下你原代码里的问题:

  • 条件判断错误:你用了if df['id'][row] > 1,这是在判断ID的数值大于1,而不是判断当前ID是否存在其他行。正确的条件应该是df['others_count'][row] > 1(也就是当前行不是该ID的第一行)。
  • 循环效率低:逐行遍历DataFrame在数据量大的时候会非常慢,Pandas的核心优势是向量化操作,应该尽量避免循环。

下面给你两种高效的向量化解决方案,完美解决你的需求:

方法一:用expanding().mean()结合shift()

这种方法直接利用分组后的滚动均值,再偏移一行(排除当前行),逻辑清晰简洁:

import numpy as np
import pandas as pd

# 构造你的示例数据
size = 10
d = { 'id': np.array([3,4,1,6,4,8,8,7,9,1]), 'value': np.array([76,12,96,33,49,72,68,78,99,66]) }
df = pd.DataFrame(data=d)
df['others_count'] = df.groupby(['id']).cumcount() + 1

# 计算每个ID组内的滚动均值(不包含当前行)
df['value_estimated'] = df.groupby('id')['value'].apply(
    lambda x: x.expanding().mean().shift()
)

# 对于ID的第一行(others_count=1),设置为NaN(因为没有上方行)
df.loc[df['others_count'] == 1, 'value_estimated'] = np.nan

运行后得到的结果完全符合预期:

idvalueothers_countvalue_estimated
03761NaN
14121NaN
21961NaN
36331NaN
4449212.0
58721NaN
6868272.0
77781NaN
89991NaN
9166296.0

方法二:用cumsum()和cumcount()手动计算均值

如果你想更直观地控制均值的计算过程,可以用累计和减去当前值得到前n-1行的和,再除以累计行数减1:

# 计算每个ID组内当前行之前的value总和
df['sum_prev'] = df.groupby('id')['value'].cumsum() - df['value']
# 计算每个ID组内当前行之前的行数
df['count_prev'] = df.groupby('id')['value'].cumcount()

# 计算均值,同时处理除数为0的情况(others_count=1时count_prev=0)
df['value_estimated'] = np.where(
    df['others_count'] > 1,
    df['sum_prev'] / df['count_prev'],
    np.nan
)

# 可以删除中间辅助列
df = df.drop(['sum_prev', 'count_prev'], axis=1)

这个方法同样是向量化操作,效率和方法一相当,结果完全一致。

为什么这两种方法更好?

  • 效率高:向量化操作是Pandas的最优实践,比循环快几个数量级,尤其是当数据量达到万级甚至百万级时,差距会非常明显。
  • 逻辑清晰:直接利用分组和窗口函数,代码可读性强,不容易出现像原循环里的条件判断错误。
  • 稳定性好:避免了逐行操作可能带来的索引错误、性能瓶颈等问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:14:51