如何在Pandas透视表中为多列(含ind_any)实现同层级计数?
实现包含ind_any层级的透视表布局
我来帮你搞定这个透视表需求,结合你的模拟数据,咱们一步步实现你想要的布局:
首先先把你的模拟数据转换成可操作的Pandas DataFrame:
import pandas as pd data = [ [1, "thing_1", "place_1", "ind_1", "ind_any"], [2, "thing_3", "place_2", "ind_2", "ind_any"], [3, "thing_2", "place_1", "ind_1", "ind_any"], [4, "thing_1", "place_1", "ind_1", "ind_any"], [5, "thing_2", "place_3", "ind_2", "ind_any"] ] df = pd.DataFrame(data, columns=["trans_id", "prod_id", "loc", "ind_1_or_ind_2", "ind_any"])
方法一:手动构建多级列透视表
这种方式逻辑清晰,适合快速匹配你的需求:
1. 先算每个分组的总记录数
用来后续计算占比:
group_totals = df.groupby(["loc", "prod_id"]).size().rename("total")
2. 统计ind_1/ind_2的数量和占比
对ind_1_or_ind_2字段做分组计数,再计算占比:
# 统计各ind类型的数量 ind_counts = df.groupby(["loc", "prod_id", "ind_1_or_ind_2"]).size().unstack(fill_value=0) # 计算占比并保留两位小数 ind_pct = (ind_counts.div(group_totals, axis=0) * 100).round(2)
3. 统计ind_any的数量和占比
因为你的数据里ind_any全是同一值,所以每个分组的数量就是总记录数,占比固定100%:
ind_any_counts = group_totals.rename("ind_any") ind_any_pct = pd.Series([100.0]*len(ind_any_counts), index=ind_any_counts.index, name="ind_any")
4. 合并成目标多级列结构
把计数和占比组合成(n)(%)的子列,再把ind_1、ind_2、ind_any放在同一层级:
# 组合ind_1/ind_2的n和%,调整列层级顺序 ind_combined = pd.concat([ind_counts, ind_pct], keys=["(n)", "(%)"], axis=1).swaplevel(0,1,axis=1).sort_index(axis=1) # 组合ind_any的n和%,构建多级列 any_combined = pd.concat([ind_any_counts, ind_any_pct], keys=["(n)", "(%)"], axis=1) any_combined.columns = pd.MultiIndex.from_tuples([("ind_any", "(n)"), ("ind_any", "(%)")]) # 合并所有列得到最终透视表 final_pivot = pd.concat([ind_combined, any_combined], axis=1)
打印final_pivot就能得到你想要的布局:
ind_1 ind_2 ind_any (n) (%) (n) (%) (n) (%) loc prod_id place_1 thing_1 2 100 0 0 2 100.0 thing_2 1 100 0 0 1 100.0 place_2 thing_3 0 0 1 100 1 100.0 place_3 thing_2 0 0 1 100 1 100.0
方法二:用melt重塑数据后透视(更灵活)
如果后续要加更多类似ind_any的指标,这个方法扩展性更强:
# 重塑数据:把ind_1_or_ind_2和ind_any转成同一维度的指标列 melted = pd.melt(df, id_vars=["trans_id", "prod_id", "loc"], value_vars=["ind_1_or_ind_2", "ind_any"], var_name="indicator_type", value_name="indicator") # 分组统计各指标的数量 counts = melted.groupby(["loc", "prod_id", "indicator"]).size().unstack(fill_value=0) # 计算各指标的占比 pcts = (counts.div(counts.sum(axis=1), axis=0)*100).round(2) # 合并数量和占比,调整列层级 final_pivot = pd.concat([counts, pcts], keys=["(n)", "(%)"], axis=1).swaplevel(0,1,axis=1).sort_index(axis=1)
这个方法只需要在value_vars里添加新指标,就能自动纳入透视表,非常省心。
内容的提问来源于stack exchange,提问作者Pylander
相关产品推荐
相关产品推荐

