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

如何对pandas DataFrame按分组原地应用自定义zscore函数?

问题根因

你的代码修改不生效,核心原因是df.query("MonthNumber == @month")返回的是原始DataFrame的副本,不是指向原数据的视图,你在函数内对这个副本做的任何列赋值操作,都不会同步到原始df上,这是pandas的索引返回机制决定的,和Python函数传参逻辑无关。

实现方法

推荐方案:用groupby+transform原生分组计算(无手动循环,性能更好)

不需要手动遍历月份、不需要写自定义函数处理副本问题,pandas原生的分组转换逻辑会自动按组计算并对齐原始行索引,直接赋值即可原地修改原始df:

# 修正原代码里的拼写错误:compure -> compute
columns = ['T_AROME', 'T_ARPEGE']
grouped = df.groupby('MonthNumber')[columns]
# 按分组计算zscore,结果直接对齐原始df的行
df[columns] = grouped.transform(lambda x: (x - x.mean()) / x.std(ddof=0))

保留自定义函数的方案:直接在函数内定位原始df的目标行修改

如果你需要保留自定义函数的结构,不要把query返回的副本传入函数,改为传入原始df和月份筛选条件,用loc直接定位原始df的对应位置赋值,就能实现原地修改的效果:

def compute_z_score(raw_df, target_month, columns):
    # 生成原始df中对应月份的行筛选掩码
    month_filter = raw_df['MonthNumber'] == target_month
    for col in columns:
        target_col = raw_df.loc[month_filter, col]
        # 直接对原始df的对应位置赋值,不操作中间副本
        raw_df.loc[month_filter, col] = (target_col - target_col.mean()) / target_col.std(ddof=0)

months = df['MonthNumber'].unique().tolist()
columns = ['T_AROME', 'T_ARPEGE']
for month in months:
    compute_z_score(df, month, columns)

注意:不建议通过强行设置pandas参数、修改链式赋值规则的方式让query返回的副本可写,这种方式会触发SettingWithCopyWarning,后续版本pandas也不保证行为一致,出问题排查成本极高。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 10:01:08