如何在Pandas中按类别分组并将分位数转换为列
解决分组分位数的宽表转换问题
当然可以!你只需要在现有代码基础上,添加一步索引重塑的操作,就能把多层索引的结果转换成你想要的宽表格式。下面是具体的实现步骤:
1. 先还原你的示例数据
首先我们先创建你给出的DataFrame,方便后续演示:
import pandas as pd data = { 'id': [1, 2, 3, 6, 0, 7], 'category': ['a', 'a', 'a', 'a', 'b', 'c'], 'price': [50, 30, 10, 5, 20, 80] } df = pd.DataFrame(data)
2. 你的原始代码及问题
你执行的分组分位数代码会返回多层行索引的结果(category是第一层,分位数是第二层):
quantile = df[['category', 'price']].groupby('category').quantile([0.25, 0.5, 0.75]) print(quantile)
输出结果(简化版):
price category a 0.25 10.0 0.50 20.0 0.75 30.0 b 0.25 20.0 0.50 20.0 0.75 20.0
3. 转换为目标格式的方法
方法一:用unstack()重塑索引
unstack()可以把内层的行索引(分位数)转换为列,之后再做简单的列名整理即可:
# 计算分位数并转宽表 quantile_wide = df[['category', 'price']].groupby('category').quantile([0.25, 0.5, 0.75]).unstack() # 扁平化列名(去掉第一层的'price'索引) quantile_wide = quantile_wide.droplevel(0, axis=1) # 将category从行索引转为普通列,并设置列名 quantile_wide = quantile_wide.reset_index() quantile_wide.columns = ['category', '0.25', '0.5', '0.75'] print(quantile_wide)
最终输出就是你想要的格式:
category 0.25 0.5 0.75 0 a 10.0 20.0 30.0 1 b 20.0 20.0 20.0 2 c 80.0 80.0 80.0
方法二:用agg()直接指定列名(更直观)
如果你想一步到位生成目标格式,也可以用groupby.agg()结合lambda函数,直接定义分位数列名:
quantile_wide = df.groupby('category')['price'].agg( **{str(q): lambda x: x.quantile(q) for q in [0.25, 0.5, 0.75]} ).reset_index() print(quantile_wide)
这个方法会直接生成符合要求的宽表,不需要额外的索引整理步骤,结果和方法一完全一致。
关键原理说明
unstack():Pandas中用于将行索引的层级“展开”为列的工具,这里把分位数层级从行移到列,实现长表转宽表。droplevel():因为quantile()返回的结果列名是多层的(('price', 0.25)),所以需要去掉第一层的price,让列名直接显示分位数。
内容的提问来源于stack exchange,提问作者Shubham R
相关产品推荐
相关产品推荐

