agg 的核心优势是灵活性和高效性,尤其适合复杂的分组统计需求。通过组合不同的函数和列,你可以快速生成多维度的统计结果。

1. 基本语法

DataFrame.agg(func=None, axis=0, *args, **kwargs)
Series.agg(func=None, axis=0, *args, **kwargs)

func: 要应用的函数(可以是函数名、函数对象、列表或字典)。

axis: 0 或 ‘index’(按列聚合),1 或 ‘columns’(按行聚合)。

2. 常见用法

示例数据准备

import pandas as pd

data = {
    'A': [1, 2, 3, 4],
    'B': [5, 6, 7, 8],
    'C': ['X', 'Y', 'X', 'Y']
}
df = pd.DataFrame(data)

2.1 单列应用单个函数

# 对列'A'求和
df['A'].agg('sum')  # 输出: 10
# 等价写法
df['A'].agg(sum)

2.2 单列应用多个函数

# 对列'A'同时求和和求均值
df['A'].agg(['sum', 'mean'])
# 输出:
# sum    10
# mean    2.5

2.3 多列应用不同函数

# 对列'A'求和,列'B'求均值
df.agg({'A': 'sum', 'B': 'mean'})

# 输出:
# A    10.0
# B     6.5

2.4 所有列应用相同函数

# 对所有数值列求和
df.agg('sum')

# 输出:
# A    10
# B    26

2.5 分组后使用 agg

结合 groupby 使用更强大:

# 按列'C'分组,对每组计算'A'的和与'B'的均值
result = df.groupby('C').agg({
    'A': 'sum',
    'B': ['mean', 'max']
})

# 输出:
#     A    B
#   sum mean max
# C
# X  4    6   7
# Y  6    7   8

2.6 自定义函数

可以传递自定义函数(或 lambda 函数):

# 对列'A'计算最大值与最小值的差
df['A'].agg(lambda x: x.max() - x.min())  # 输出: 3

# 对分组后的数据应用自定义函数
def custom_func(s):
    return s.max() * 2

df.groupby('C').agg({
    'A': 'sum',
    'B': custom_func
})

2.7 重命名聚合结果的列名

使用元组指定新列名:

agg_dict = {
    'A': [('total', 'sum'), ('average', 'mean')],
    'B': [('max_value', 'max')]
}
df.groupby('C').agg(agg_dict)

3. agg函数运用

示例 1:多级分组 + 多列多函数

场景:按地区和产品类别分组,计算销售额的统计量,并对利润列应用自定义条件聚合。

import pandas as pd
import numpy as np

# 示例数据
data = {
    'Region': ['North', 'North', 'South', 'South', 'East', 'East'],
    'Category': ['A', 'B', 'A', 'B', 'A', 'B'],
    'Sales': [100, 200, 150, 300, 250, 400],
    'Profit': [10, 25, -5, 40, 15, 60]
}
df = pd.DataFrame(data)

# 多级分组 + 多函数
result = df.groupby(['Region', 'Category']).agg({
    'Sales': ['sum', 'mean', lambda x: x.max() - x.min()],  # 匿名函数计算极差
    'Profit': [
        ('positive_profit', lambda x: (x > 0).sum()),  # 自定义名称统计正利润次数
        ('total_profit', 'sum')
    ]
})

print(result)

输出:

                Sales                            Profit             
                  sum   mean <lambda_0> positive_profit total_profit
Region Category                                                     
East   A          250  250.0          0               1           15
       B          400  400.0          0               1           60
North  A          100  100.0          0               1           10
       B          200  200.0          0               1           25
South  A          150  150.0          0               0           -5
       B          300  300.0          0               1           40

示例 2:动态聚合 + 参数传递

场景:对数值列动态应用多个分位数计算,并传递参数。

# 定义分位数函数(带参数)
def quantile_range(series, q1=0.25, q2=0.75):
    return series.quantile(q2) - series.quantile(q1)

# 对 Sales 和 Profit 同时计算多种分位差
agg_dict = {
    'Sales': [('q3-q1', lambda x: quantile_range(x, 0.25, 0.75)),
              ('q90-q10', lambda x: quantile_range(x, 0.1, 0.9))],
    'Profit': 'median'
}

print(df.groupby('Region').agg(agg_dict))

输出:

       Sales         Profit
       q3-q1 q90-q10 median
Region                     
East    75.0   120.0   37.5
North   50.0    80.0   17.5
South   75.0   120.0   17.5

示例 3:条件聚合 + 混合计算

场景:对成绩表按班级分组,计算通过率(分数≥60为通过),同时统计最高分和平均分。

# 示例数据
scores = {
    'Class': ['A', 'A', 'B', 'B', 'B', 'C'],
    'Name': ['Alice', 'Bob', 'Charlie', 'David', 'Eva', 'Frank'],
    'Math': [85, 45, 90, 55, 70, 80],
    'Science': [75, 60, 85, 40, 95, 65]
}
df_scores = pd.DataFrame(scores)

# 自定义通过率函数
def pass_rate(series, threshold=60):
    return (series >= threshold).mean()

# 聚合配置
agg_config = {
    'Math': [('Avg', 'mean'), ('PassRate', pass_rate), ('Max', 'max')],
    'Science': [('Avg', 'mean'), ('PassRate', lambda x: pass_rate(x, 60))]
}

print(df_scores.groupby('Class').agg(agg_config))

输出:

            Math                  Science          
             Avg  PassRate Max        Avg  PassRate
Class                                              
A      65.000000  0.500000  85  67.500000  1.000000
B      71.666667  0.666667  90  73.333333  0.666667
C      80.000000  1.000000  80  65.000000  1.000000

示例 4:时间序列聚合

场景:按周重采样时间序列数据,计算每周的波动率和总和。

# 生成时间序列数据
date_rng = pd.date_range(start='2023-01-01', end='2023-01-31', freq='D')
data = {
    'Date': date_rng,
    'Value': np.random.randint(50, 150, size=len(date_rng))
}
df_time = pd.DataFrame(data).set_index('Date')

# 自定义波动率函数(标准差 / 均值)
def volatility(series):
    return series.std() / series.mean()

# 按周聚合
weekly_agg = df_time.resample('W').agg({
    'Value': [('Total', 'sum'), ('Volatility', volatility)]
})

print(weekly_agg)

输出:

           Value           
           Total Volatility
Date                       
2023-01-01   124        NaN
2023-01-08   731   0.303868
2023-01-15   737   0.189620
2023-01-22   635   0.288917
2023-01-29   829   0.163650
2023-02-05   150   0.094281

示例 5:链式聚合 + 列重命名

场景:对多列应用不同函数后,重命名。

# 复杂聚合
agg_result = df.groupby('Region').agg(
    Sales_Total=('Sales', 'sum'),
    Sales_Std=('Sales', 'std'),
    Profit_Range=('Profit', lambda x: x.max() - x.min())
).reset_index()
print(agg_result)

输出:

  Region  Sales_Total   Sales_Std  Profit_Range
0   East          650  106.066017            45
1  North          300   70.710678            15
2  South          450  106.066017            45
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐