在数据处理工作中,经常需要把数据先按某个字段归类,再分别计算每一类的平均值、总和或记录数。Python的pandas库提供了groupby方法,它把“分组”和“聚合”两个动作连在一起,让统计逻辑变得直观。理解它的内部执行方式,比死记函数参数更有用。

一、groupby的基本工作原理
groupby操作在pandas中遵循“拆分、应用、合并”的模型。拆分阶段会根据你指定的键(比如某一列的值)把原始DataFrame切成多个小组;应用阶段对每个小组执行你给的聚合函数;合并阶段把各组结果拼回一个结构化的输出。这种机制避免了手写循环遍历每行判断归属的低效做法。
从代码角度看,groupby返回的是一个GroupBy对象,而不是立刻算出结果。只有当你接上mean、sum、count这类聚合方法,或者显式调用agg时,pandas才会真正执行计算。这也意味着你可以先分组,再灵活决定要算什么,而不用反复扫描数据。
import pandas as pd
data = {
'region': ['华北', '华北', '华南', '华南', '华南'],
'sales': [200, 150, 300, 250, 400],
'orders': [2, 1, 3, 2, 4]
}
df = pd.DataFrame(data)
# 仅分组,返回GroupBy对象,未计算
grouped = df.groupby('region')
print(type(grouped))
# 应用聚合,触发计算
result = grouped.mean()
print(result)
二、用mean按组计算平均值
mean是最常用的聚合函数之一,用来观察每组在某个数值列上的平均水平。比如上面例子中,想看每个地区的平均销售额,直接对分组对象调用mean即可。如果不指定列,pandas会对所有数值列求平均;如果只关心某一列,可以用中括号先选列再聚合,减少不必要的计算。
需要注意,mean会自动忽略NaN值。如果某组全部是缺失值,结果会是NaN而不是报错。另外,分组键中如果存在NaN,pandas默认把它当作一个独立分组,这点常在清洗不彻底的数据时带来意外统计,建议先dropna处理键值。
# 只计算销售额的平均值
avg_sales = df.groupby('region')['sales'].mean()
print(avg_sales)
# 多列同时求平均
avg_all = df.groupby('region').mean()
print(avg_all)
三、用sum按组求和
sum适合统计累计量,例如各地区的总销售额、总订单数。和mean不同,sum会把组内数值直接相加,NaN被视为0参与运算(在pandas中默认skipna=True,等效于忽略缺失)。当你需要看规模而非水平时,sum比mean更合适。
使用sum时一个常见误区是对非数值列分组后误用sum,pandas会对字符串列做连接操作,导致结果难以解释。因此聚合前最好确认选中列的类型,或者用agg显式限定函数作用范围。
# 各地区销售与订单总和
total = df.groupby('region').sum()
print(total)
# 仅对销售额求和
total_sales = df.groupby('region')['sales'].sum()
print(total_sales)
四、用count与size统计组内记录数
count返回每组中非NaN值的个数,而size返回每组的总行数(包含NaN)。这两个函数容易混淆。当你想统计“有多少个订单记录”时,如果订单字段有缺失,count会少算,size才反映真实条数。在用户行为分析中,size常用来衡量活跃度。
从性能上说,size比count略快,因为它不需要检查每列缺失情况。若只需知道分组后各组的体量,优先用size。下面示例展示二者差异,以及如何在同一表达式中组合多个聚合。
# 非NaN计数
cnt = df.groupby('region').count()
print(cnt)
# 总行数计数
sz = df.groupby('region').size()
print(sz)
# 组合多个聚合
summary = df.groupby('region').agg(
avg_sales=('sales', 'mean'),
total_sales=('sales', 'sum'),
record_num=('sales', 'size')
)
print(summary)
五、聚合结果的索引与后续处理
默认情况下,groupby的键会成为结果DataFrame的索引。这方便用loc取值,但在后续与其他表合并时,往往需要先reset_index把键变回普通列。另外,多列分组会产生多层索引,可用tuple访问或flat处理,避免出错。
当分组逻辑复杂时,可传入字典或Series作为键映射,甚至用lambda对索引分组。掌握这些技巧后,mean、sum、count只是基础积木,真正价值在于用清晰语法表达业务统计规则,让代码兼具正确性与可维护性。
# 重置索引便于后续操作 summary_reset = summary.reset_index() print(summary_reset) # 多列分组示例 df['year'] = [2021, 2021, 2022, 2022, 2022] multi = df.groupby(['region', 'year'])['sales'].sum() print(multi)
Pythongroupbypandas_aggregate修改时间:2026-08-05 11:33:34