author: 专注Python实战,分享爬虫与数据分析干货
title: Python爬虫实战⑱|Pandas分组聚合,一键生成统计报表
update: 2026-04-26
tags: Python,Pandas,分组,聚合,groupby,agg,透视表,统计报表
作者:专注Python实战,分享爬虫与数据分析干货
更新时间:2026年4月
适合人群:有Pandas基础、想掌握分组统计的开发者
前言:10万条数据,如何一眼看出规律?
爬了10万条商品数据,老板问:
- 每个品类平均价格多少?
- 哪个城市销量最高?
- 每月销售额趋势怎样?
groupby = 数据分析的"瑞士军刀"。 一行代码,搞定80%的统计需求。
一、groupby基础
1.1 基本语法
python
import pandas as pd
df = pd.DataFrame({
"城市": ["北京", "上海", "北京", "广州", "上海", "广州", "北京", "上海"],
"品类": ["手机", "电脑", "电脑", "手机", "手机", "电脑", "手机", "电脑"],
"销量": [120, 80, 95, 110, 130, 75, 140, 90],
"价格": [3999, 6999, 5999, 3499, 4299, 5499, 3799, 7499],
})
# 按城市分组
grouped = df.groupby("城市")
print(type(grouped)) # DataFrameGroupBy对象
# 查看分组
for name, group in grouped:
print(f"\n{name}:")
print(group)
# 按城市统计销量
print(df.groupby("城市")["销量"].sum())
# 北京 355
# 广州 185
# 上海 300
1.2 常用聚合函数
python
# 求和
df.groupby("城市")["销量"].sum()
# 均值
df.groupby("城市")["价格"].mean()
# 计数
df.groupby("城市")["销量"].count()
# 最大/最小
df.groupby("城市")["价格"].max()
df.groupby("城市")["价格"].min()
# 标准差
df.groupby("城市")["价格"].std()
# 中位数
df.groupby("城市")["价格"].median()
# 多统计量
df.groupby("城市")["价格"].describe()
二、多列聚合
2.1 同时统计多列
python
# 多列同一聚合
df.groupby("城市")[["销量", "价格"]].mean()
# 多列不同聚合(agg)
result = df.groupby("城市").agg({
"销量": ["sum", "mean", "max"],
"价格": ["mean", "min", "max"],
})
print(result)
# 自定义列名
result = df.groupby("城市").agg(
总销量=("销量", "sum"),
平均销量=("销量", "mean"),
平均价格=("价格", "mean"),
最高价格=("价格", "max"),
商品数量=("价格", "count"),
)
print(result)
2.2 自定义聚合函数
python
# 极差(最大-最小)
def price_range(x):
return x.max() - x.min()
result = df.groupby("城市").agg(
平均价格=("价格", "mean"),
价格极差=("价格", price_range),
销量总和=("销量", "sum"),
)
print(result)
# lambda函数
result = df.groupby("城市").agg(
平均价格=("价格", "mean"),
价格变异系数=("价格", lambda x: x.std() / x.mean()),
)
三、多级分组
python
# 按城市和品类分组
result = df.groupby(["城市", "品类"]).agg(
总销量=("销量", "sum"),
平均价格=("价格", "mean"),
)
print(result)
# 取消多级索引
result = df.groupby(["城市", "品类"]).agg(
总销量=("销量", "sum"),
平均价格=("价格", "mean"),
).reset_index()
print(result)
四、透视表(pivot_table)
python
# 基本透视表
pivot = pd.pivot_table(
df,
values="销量", # 值字段
index="城市", # 行
columns="品类", # 列
aggfunc="sum", # 聚合函数
fill_value=0, # 空值填充
margins=True, # 显示合计
)
print(pivot)
# 多值字段透视
pivot = pd.pivot_table(
df,
values=["销量", "价格"],
index="城市",
columns="品类",
aggfunc={"销量": "sum", "价格": "mean"},
fill_value=0,
)
print(pivot)
五、交叉表(crosstab)
python
# 频次统计
cross = pd.crosstab(df["城市"], df["品类"])
print(cross)
# 带归一化
cross_pct = pd.crosstab(df["城市"], df["品类"], normalize="index") # 行归一化
print(cross_pct.round(2))
六、实战:电商数据分析
python
import pandas as pd
# 模拟电商数据
df = pd.read_csv("ecommerce_orders.csv", encoding="utf-8-sig")
# 1. 按品类统计
category_stats = df.groupby("品类").agg(
订单数=("订单ID", "count"),
总销售额=("金额", "sum"),
平均单价=("金额", "mean"),
最高单价=("金额", "max"),
).sort_values("总销售额", ascending=False)
print("=== 品类统计 ===")
print(category_stats)
# 2. 按月份统计趋势
df["月份"] = pd.to_datetime(df["日期"]).dt.to_period("M")
monthly = df.groupby("月份").agg(
订单数=("订单ID", "count"),
总销售额=("金额", "sum"),
平均客单价=("金额", "mean"),
)
print("\n=== 月度趋势 ===")
print(monthly)
# 3. 按城市+品类交叉统计
city_category = pd.pivot_table(
df, values="金额", index="城市", columns="品类",
aggfunc="sum", fill_value=0, margins=True,
)
print("\n=== 城市×品类 ===")
print(city_category)
# 4. Top10热门商品
top_products = df.groupby("商品名").agg(
总销量=("数量", "sum"),
总销售额=("金额", "sum"),
).sort_values("总销量", ascending=False).head(10)
print("\n=== Top10商品 ===")
print(top_products)
# 5. 用户分层(RFM简化版)
user_stats = df.groupby("用户ID").agg(
最近购买=("日期", "max"),
购买次数=("订单ID", "count"),
总消费=("金额", "sum"),
).sort_values("总消费", ascending=False)
print("\n=== 用户统计 ===")
print(user_stats.head(10))
七、知识卡
| 方法 | 说明 |
|---|---|
| df.groupby() | 分组 |
| .sum() / .mean() | 求和/均值 |
| .count() | 计数 |
| .agg() | 多种聚合 |
| .describe() | 完整统计 |
| pd.pivot_table() | 透视表 |
| pd.crosstab() | 交叉表 |
| .reset_index() | 取消多级索引 |
| margins=True | 显示合计行 |
| normalize | 归一化 |
八、课后作业
必做题:
- 读取爬虫数据,按分类统计均值和总和
- 用pivot_table生成交叉统计表
- 找出Top10热门商品
选做题:
- 实现RFM用户分层分析
- 按月度统计销售趋势
有问题欢迎评论区留言,大家一起讨论!
标签:Python | Pandas | 分组聚合 | groupby | 透视表 | 统计报表