欢迎光临易鼎网
详情描述

groupby().agg()有两种常见的写法,它们在使用场景和灵活性上有所不同:

1. 两种写法对比

写法一:字典形式(推荐用于多个聚合)

# 对不同的列应用不同的聚合函数
df.groupby('group_col').agg({
    'col1': 'sum',
    'col2': ['mean', 'std'],
    'col3': lambda x: x.max() - x.min()
})

写法二:命名参数形式(推荐用于单个聚合)

# 对多个列应用相同的聚合函数
df.groupby('group_col').agg(
    total_sales=('sales', 'sum'),
    avg_price=('price', 'mean'),
    custom_metric=('value', lambda x: x.quantile(0.9))
)

2. 核心区别

字典形式的特点:

# 多级索引的列名(自动命名)
result = df.groupby('group').agg({
    'A': ['sum', 'mean'],
    'B': 'max'
})

# 输出列名会是:
#     A          B
#   sum  mean  max

命名参数形式的特点:

# 单级索引的自定义列名
result = df.groupby('group').agg(
    total_A=('A', 'sum'),
    avg_A=('A', 'mean'),
    max_B=('B', 'max')
)

# 输出列名是:
#   total_A  avg_A  max_B

3. 实际使用中的选择建议

选择字典形式的情况:

  • 需要多级列名(MultiIndex columns)
  • 批量对多个列应用相同的函数
  • 使用匿名函数或自定义函数
# 批量聚合示例
agg_dict = {
    'sales': ['sum', 'mean', 'count'],
    'profit': ['sum', 'mean'],
    'quantity': 'sum'
}
df.groupby('date').agg(agg_dict)

选择命名参数形式的情况:

  • 需要清晰的列名(业务可读性)
  • 对少数几个列进行聚合
  • 结果需要进一步处理(避免MultiIndex)
# 创建业务友好的列名
summary = df.groupby('department').agg(
    total_revenue=('revenue', 'sum'),
    avg_salary=('salary', 'mean'),
    employee_count=('employee_id', 'nunique'),
    top_performer=('performance_score', lambda x: x.nlargest(1).iloc[0])
)

4. 混合使用技巧

# 可以混合使用(Pandas 1.0+)
result = df.groupby('group').agg(
    total=('value', 'sum'),
    **{'value': ['mean', 'std']}  # 保留原列名的多级索引
)

5. 性能考虑

两种写法在性能上差异不大,主要区别在于:

  • 字典形式:更简洁,适合快速探索
  • 命名参数形式:更明确,适合生产代码
# 性能对比(通常差异很小)
import time

start = time.time()
result1 = df.groupby('group').agg({'col': ['sum', 'mean']})
print(f"字典形式: {time.time()-start:.4f}s")

start = time.time()
result2 = df.groupby('group').agg(
    sum_col=('col', 'sum'),
    mean_col=('col', 'mean')
)
print(f"命名参数: {time.time()-start:.4f}s")

6. 最佳实践总结

场景 推荐写法 理由
探索性分析 字典形式 快速、简洁
生产代码 命名参数形式 列名清晰,易于维护
多列相同聚合 字典形式 {'col1':'mean', 'col2':'mean'}
单个列多个聚合 字典形式 {'col': ['sum', 'mean', 'std']}
需要自定义列名 命名参数形式 直接指定有意义的列名

最实用的建议:

  • 临时分析用字典形式
  • 要保留的代码用命名参数形式(更好的可读性)
  • 根据具体需求灵活选择,两者可以互相转换