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

如何为Pandas DataFrame各列自定义GroupBy函数?如何捕捉跨季节值变化?

搞定Pandas Groupby自定义函数+季节间数值变化的方案

咱先从你问的第一个问题说起:怎么用groupby给每列应用自定义函数,得到想要的结果。我给你分两种常见场景,配示例代码,一看就懂。

一、Groupby后为每列应用自定义函数

首先咱先造个贴近业务的示例数据:

import pandas as pd
import numpy as np

# 构造包含ID、年份、季节、销量、利润的示例DataFrame
data = {
    'ID': ['A', 'A', 'A', 'B', 'B', 'C', 'C', 'C'],
    'Year': [2021, 2021, 2022, 2021, 2022, 2021, 2022, 2022],
    'Season': ['春', '秋', '春', '夏', '夏', '春', '秋', '冬'],
    'Sales': [100, 150, 120, 80, 90, 200, 220, 180],
    'Profit': [20, 30, 25, 15, 18, 40, 45, 35]
}
df = pd.DataFrame(data)

1. 所有数值列共用同一个自定义函数

比如你想给每个ID的销量、利润都计算均值、最大值,还有自定义的「峰值与均值的差值」,可以这么写:

# 定义自定义统计函数,返回Series格式方便后续展开
def custom_stats(x):
    return pd.Series({
        'mean': x.mean(),
        'max': x.max(),
        'peak_diff': x.max() - x.mean()
    })

# 按ID分组,对Sales和Profit列应用自定义函数
result = df.groupby('ID')[['Sales', 'Profit']].apply(custom_stats)
# 把多层索引展开,让结果更直观
result = result.unstack(level=1)

执行后你会得到一个清晰的结果表,每个ID对应每列的三个统计值。

2. 不同列用不同的自定义函数

如果想给销量算总和和变异系数,给利润算中位数和调整后的最小值,用agg方法的字典传参就很灵活:

# 定义两个自定义函数
def coefficient_of_variation(x):
    # 变异系数:标准差/均值*100,反映数据离散程度
    return x.std() / x.mean() * 100

def adjusted_min_profit(x):
    # 自定义利润最小值:实际最小值减5
    return x.min() - 5

# 按ID分组,指定每列对应的函数,还能自定义结果列名
result_custom = df.groupby('ID').agg(
    销量总和=('Sales', 'sum'),
    销量变异系数=('Sales', coefficient_of_variation),
    利润中位数=('Profit', 'median'),
    调整后利润最小值=('Profit', adjusted_min_profit)
)

这种方式可以精准控制每列的计算逻辑,还能直接给结果列起业务化名称,非常实用。

二、捕捉同一ID在多年多季节的数值变化

针对部分ID有多年多季节数据的情况,分两种常见场景处理:

1. 同一年份内不同季节的变化(环比)

先给季节排序(避免乱序导致计算错误),然后按ID+年份分组,用diff()或pct_change()计算变化:

# 给季节指定顺序,方便排序
season_rank = {'春':1, '夏':2, '秋':3, '冬':4}
df['Season_rank'] = df['Season'].map(season_rank)
# 按ID、年份、季节排序
df_sorted = df.sort_values(['ID', 'Year', 'Season_rank'])

# 计算同一年内,当前季节与上一季节的销量差值和变化率
df_sorted['销量季节差值'] = df_sorted.groupby(['ID', 'Year'])['Sales'].diff()
df_sorted['销量季节变化率(%)'] = df_sorted.groupby(['ID', 'Year'])['Sales'].pct_change() * 100

这样你就能看到每个ID每年里,春到秋、秋到冬这类季节间的销量波动。

2. 同一季节不同年份的变化(同比)

按ID+季节分组,计算跨年度的变化:

# 按ID、季节、年份排序
df_yoy_sorted = df.sort_values(['ID', 'Season', 'Year'])

# 计算同一季节,今年与去年的销量差值和同比变化率
df_yoy_sorted['销量同比差值'] = df_yoy_sorted.groupby(['ID', 'Season'])['Sales'].diff()
df_yoy_sorted['销量同比变化率(%)'] = df_yoy_sorted.groupby(['ID', 'Season'])['Sales'].pct_change() * 100

比如ID A的2022年春 vs 2021年春的销量变化,就能直接看到。

3. 用透视表直观对比所有季节数据

如果想一次性查看所有年份-季节的数值对比,用pivot_table转成宽表更清晰:

# 生成透视表:行是ID,列是年份-季节,值是销量
pivot_df = df.pivot_table(index='ID', columns=['Year', 'Season'], values='Sales', aggfunc='first')
# 直接计算指定季节的跨年度差值,比如2022春 vs 2021春
pivot_df['2022春_vs_2021春'] = pivot_df[(2022, '春')] - pivot_df[(2021, '春')]

这种方式适合做全局对比,一眼就能看到每个ID的季节数据变化趋势。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:50:16