如何在Pandas中按分类生成分组计数的占比列?
Pandas实现分组计数占分类总数比例的问题
需求说明:
需要在species_df数据框中新增一列,用于表示分组计数占对应分类总计数的比例。具体步骤为:
- 按
category和conservation_status分组,统计scientific_name的数量得到count列; - 将每行的
count值除以该category的总count值,生成新列。
示例效果参考:
| count | new_column |
|---|---|
| 1 | .01 |
| 73 | .91 |
| 4 | .05 |
| 2 | .03 |
我尝试了以下代码:
species_df.groupby(['category', 'conservation_status']).scientific_name.count() / species_df.groupby('category').scientific_name.count()
但返回错误:
TypeError: incompatible index of inserted column with frame index
希望实现类似SQL窗口函数的效果,请求解决。
附species_df数据示例:
# species_df dataframe {'category': {0: 'Mammal', 1: 'Mammal', 2: 'Mammal', 3: 'Mammal', 4: 'Mammal'}, 'scientific_name': {0: 'Clethrionomys gapperi gapperi', 1: 'Bos bison', 2: 'Bos taurus', 3: 'Ovis aries', 4: 'Cervus elaphus'}, 'common_names': {0: "Gapper's Red-Backed Vole", 1: 'American Bison, Bison', 2: 'Aurochs, Aurochs, Domestic Cattle (Feral), Domesticated Cattle', 3: 'Domestic Sheep, Mouflon, Red Sheep, Sheep (Feral)', 4: 'Wapiti Or Elk'}, 'conservation_status': {0: 'None', 1: 'None', 2: 'None', 3: 'None', 4: 'None'}}
解决方案
你的问题核心是两个分组结果的索引不匹配:第一个分组是多级索引(category+conservation_status),第二个是单级索引(category),直接除法会导致索引对齐失败。以下是几种能实现类似SQL窗口函数效果的解决方法:
方法1:用transform直接计算(最简洁)
transform会将聚合结果广播回原数据框的每一行,自动处理索引对齐:
# 先计算分组计数,添加count列 species_df['count'] = species_df.groupby(['category', 'conservation_status'])['scientific_name'].transform('count') # 计算每个category的总计数,再求比例 species_df['new_column'] = species_df['count'] / species_df.groupby('category')['scientific_name'].transform('count')
方法2:先聚合再合并
如果需要先得到汇总结果再关联回原数据,可采用此方法:
# 1. 按双维度分组统计count grouped_count = species_df.groupby(['category', 'conservation_status'])['scientific_name'].count().reset_index(name='count') # 2. 统计每个category的总计数 category_total = species_df.groupby('category')['scientific_name'].count().reset_index(name='category_total') # 3. 合并并计算比例,再关联回原数据框 result = grouped_count.merge(category_total, on='category') result['new_column'] = result['count'] / result['category_total'] species_df = species_df.merge(result, on=['category', 'conservation_status'])
方法3:用value_counts直接生成比例
利用value_counts的normalize参数,一步得到分类内的占比:
# 得到每个category下各conservation_status的占比 proportion = species_df.groupby('category')['conservation_status'].value_counts(normalize=True).rename('new_column').reset_index() # 统计分组count count = species_df.groupby(['category', 'conservation_status'])['scientific_name'].count().rename('count').reset_index() # 合并后关联回原数据框 species_df = species_df.merge(count.merge(proportion, on=['category', 'conservation_status']), on=['category', 'conservation_status'])
以上三种方法都能解决索引不匹配的问题,实现你需要的比例计算效果。
内容的提问来源于stack exchange,提问作者Keith Taylor
相关产品推荐
相关产品推荐

