如何对同一Pandas DataFrame连续分组统计并保留各步结果
Pandas三层递进分组统计实现方案
现有数据与需求
示例DataFrame结构如下:
car_model store_location year_buying car_color Ferrari LA 2010 Red Ferrari LA 2010 Pink Ferrari Paris 2010 Yellow Mercedes LA 2012 Red Mercedes Roma 2022 Grey
需要完成三层递进统计,且完整保留所有层级的统计结果:
- 按
car_model维度分组,统计每个车型对应的不同门店数量,以及各门店下的记录条数 - 在第一层分组基础上,统计每个车型+门店组合下的不同购车年份数量,以及各年份下的记录条数
- 在第二层分组基础上,统计每个车型+门店+年份组合下的不同车身颜色数量,以及各颜色下的记录条数
之前编写的df.groupby(['car_model','store_location'])['store_location'].count()只能得到单层级的门店计数Series,没有保留分层分组的键映射关系,既无法直接承接后续钻取统计,也没法保留多层级结果。
实现思路
不要基于上一层的Series结果做二次计算,直接从最细粒度(第三层:车型+门店+年份+颜色)的分组开始往上逐层聚合,每一层通过transform挂载当前维度的去重计数,最后通过关联合并所有层级的统计字段,既可以拿到单层级的汇总表,也可以拿到包含所有层级统计值的完整宽表。
完整代码
import pandas as pd # 1. 构造示例DataFrame data = [ ["Ferrari", "LA", 2010, "Red"], ["Ferrari", "LA", 2010, "Pink"], ["Ferrari", "Paris", 2010, "Yellow"], ["Mercedes", "LA", 2012, "Red"], ["Mercedes", "Roma", 2022, "Grey"] ] df = pd.DataFrame(data, columns=["car_model", "store_location", "year_buying", "car_color"]) # 2. 第三层统计:车型+门店+年份维度下的颜色统计 level3 = df.groupby( ["car_model", "store_location", "year_buying", "car_color"] ).size().reset_index(name="color_count") # 挂载当前维度下的不同颜色总数 level3["distinct_color_per_year"] = level3.groupby( ["car_model", "store_location", "year_buying"] )["car_color"].transform("nunique") # 3. 第二层统计:车型+门店维度下的年份统计 year_agg = level3.groupby( ["car_model", "store_location", "year_buying"] )["color_count"].sum().reset_index(name="year_count") # 挂载当前维度下的不同年份总数 year_agg["distinct_year_per_store"] = year_agg.groupby( ["car_model", "store_location"] )["year_buying"].transform("nunique") # 4. 第一层统计:车型维度下的门店统计 store_agg = year_agg.groupby( ["car_model", "store_location"] )["year_count"].sum().reset_index(name="store_count") # 挂载当前维度下的不同门店总数 store_agg["distinct_store_per_model"] = store_agg.groupby( "car_model" )["store_location"].transform("nunique") # 5. 合并所有层级结果,得到包含全部统计值的完整宽表 final_result = level3.merge( year_agg.drop(columns=["year_count"]), on=["car_model", "store_location", "year_buying"] ).merge( store_agg.drop(columns=["store_count"]), on=["car_model", "store_location"] )
结果说明
- 单独查看第一层统计结果直接取
store_agg即可,示例输出:
| car_model | store_location | store_count | distinct_store_per_model |
|---|---|---|---|
| Ferrari | LA | 2 | 2 |
| Ferrari | Paris | 1 | 2 |
| Mercedes | LA | 1 | 2 |
| Mercedes | Roma | 1 | 2 |
- 单独查看第二层统计结果直接取
year_agg即可 - 单独查看第三层统计结果直接取
level3即可 - 合并后的
final_result包含所有层级的统计字段,不需要反复钻取分组就能直接看到各维度的计数结果,示例输出:
| car_model | store_location | year_buying | car_color | color_count | distinct_color_per_year | distinct_year_per_store | distinct_store_per_model |
|---|---|---|---|---|---|---|---|
| Ferrari | LA | 2010 | Pink | 1 | 2 | 1 | 2 |
| Ferrari | LA | 2010 | Red | 1 | 2 | 1 | 2 |
| Ferrari | Paris | 2010 | Yellow | 1 | 1 | 1 | 2 |
| Mercedes | LA | 2012 | Red | 1 | 1 | 1 | 2 |
| Mercedes | Roma | 2022 | Grey | 1 | 1 | 1 | 2 |
字段释义:
color_count:当前车型+门店+年份+颜色组合的记录条数distinct_color_per_year:当前车型+门店+年份组合下的不同车身颜色总数year_count:当前车型+门店+年份组合的记录条数distinct_year_per_store:当前车型+门店组合下的不同购车年份总数store_count:当前车型+门店组合的记录条数distinct_store_per_model:当前车型下的不同门店总数
内容的提问来源于stack exchange,提问作者codelifevcd
相关产品推荐
相关产品推荐

