在Pandas透视表中基于DataFrame单字段按行展示各列占比
问题:将透视表计数转换为行内占比百分比
现有示例DataFrame及透视表代码如下:
import pandas as pd d = { "year": [2021, 2021, 2021, 2021, 2022, 2022, 2022, 2023, 2023, 2023, 2023], "type": ["A", "B", "B", "A", "A", "B", "A", "B", pd.NA, "B", "A"], "observation": [22, 11, 67, 44, 2, 16, 78, 9, 10, 11, 45] } df = pd.DataFrame(d) df_pivot = pd.pivot_table( df, values="observation", index="year", columns="type", aggfunc="count" )
当前透视表按count聚合得到各年份下A、B类型的计数结果:
type A B year 2021 2 2 2022 2 1 2023 1 2
需求:将上述计数替换为各类型计数占该行总数(A+B计数和)的百分比,计算时忽略type为NA的行,每行总数可能不同,期望输出如下:
type A B year 2021 0.50 0.50 2022 0.66 0.33 2023 0.33 0.66
解决方案
方法1:先过滤NA,透视计数后计算行占比
先过滤掉type为NA的行,生成计数透视表后,用每行的计数除以该行总和得到占比,最后保留两位小数:
# 过滤type为NA的行 df_filtered = df.dropna(subset=["type"]) # 生成计数透视表 df_pivot_count = pd.pivot_table( df_filtered, values="observation", index="year", columns="type", aggfunc="count" ) # 计算行内占比并保留两位小数 df_desired_output = df_pivot_count.div(df_pivot_count.sum(axis=1), axis=0).round(2) print(df_desired_output)
方法2:用groupby + value_counts(normalize=True)一步到位
按年份分组后,对type列直接使用value_counts(normalize=True)得到组内占比,再通过unstack转换为透视表格式:
df_desired_output = ( df.dropna(subset=["type"]) .groupby("year")["type"] .value_counts(normalize=True) .unstack(fill_value=0) .round(2) ) print(df_desired_output)
方法3:分组计数后计算占比
先统计每个year-type组合的计数,再计算行内占比:
# 统计year-type的计数 counts = df.dropna(subset=["type"]).groupby(["year", "type"]).size().unstack() # 计算行占比 df_desired_output = counts.div(counts.sum(axis=1), axis=0).round(2) print(df_desired_output)
内容的提问来源于stack exchange,提问作者Arthur Dent
相关产品推荐
相关产品推荐

