如何在Pandas中按列值分组并计算各标签占比聚合结果
解决Pandas按性别计算多列标签占比的问题
问题描述
现有如下结构的Pandas DataFrame:
id gender column_1 column_2 column_3 column_n 10 male a b a b 10 female b c b c 10 male c c a a 10 male b a a b
需要生成按id和column_name分组,统计不同性别下各标签(a/b/c)的占比(百分比,保留1位小数),期望输出如下:
id column_name male_%_a male_%_b male_%_c female_%_a female_%_b female_%_c 10 column_1 33.3 33.3 33.3 0 100 0 10 column_2 33.3 33.3 33.3 0 0 100 10 column_3 100 0 0 0 100 0 10 column_n 33.3 66.7 0 0 0 100
要求适配任意数量的column_*列,DataFrame始终包含id和gender列。
解决方案
通过数据重塑+分组统计+格式调整的组合操作即可实现,步骤如下:
1. 重塑数据格式
用melt将所有column_*列转为行结构,保留id和gender作为标识列,把宽表转成便于统计的窄表:
melted_df = df.melt(id_vars=['id', 'gender'], var_name='column_name', value_name='label')
2. 计算分组标签占比
按id、gender、column_name、label分组统计计数,再计算每个标签在对应分组内的占比,转为百分比并保留1位小数:
# 统计每个分组内各标签的出现次数 counts = melted_df.groupby(['id', 'gender', 'column_name', 'label']).size().unstack(fill_value=0) # 计算占比并转为百分比格式 percentages = (counts.div(counts.sum(axis=1), axis=0) * 100).round(1)
3. 调整列名与输出格式
将性别和标签合并为指定格式的列名,再重置索引恢复id和column_name为普通列:
# 重命名列,统一为「性别_%_标签」格式 percentages.columns = [f"{gender}_%_{label}" for gender, label in percentages.columns] # 重置索引,整理成目标输出结构 result = percentages.reset_index()
完整可运行代码
import pandas as pd # 示例数据 data = { 'id': [10, 10, 10, 10], 'gender': ['male', 'female', 'male', 'male'], 'column_1': ['a', 'b', 'c', 'b'], 'column_2': ['b', 'c', 'c', 'a'], 'column_3': ['a', 'b', 'a', 'a'], 'column_n': ['b', 'c', 'a', 'b'] } df = pd.DataFrame(data) # 执行流程 melted_df = df.melt(id_vars=['id', 'gender'], var_name='column_name', value_name='label') counts = melted_df.groupby(['id', 'gender', 'column_name', 'label']).size().unstack(fill_value=0) percentages = (counts.div(counts.sum(axis=1), axis=0) * 100).round(1) percentages.columns = [f"{g}_%_{l}" for g, l in percentages.columns] result = percentages.reset_index() print(result)
运行后输出结果与需求完全匹配,且可适配任意数量的column_*列。
内容的提问来源于stack exchange,提问作者datashout
相关产品推荐
相关产品推荐

