如何用Pandas构建含分类值计数统计的透视表
解决DataFrame按行索引、列分组统计分类值出现次数的问题
嘿,我来帮你搞定这个需求!首先咱们先明确原始数据和目标要求:
原始数据情况
你给出的初始DataFrame创建代码是:
import pandas as pd test_df = pd.DataFrame({"index":[1,2,3,1],"columns":[5,6,7,5],"values":[9,9,9,9]})
它的展示效果是:
| index | columns | values | |
|---|---|---|---|
| 0 | 1 | 5 | 9 |
| 1 | 2 | 6 | 9 |
| 2 | 3 | 7 | 9 |
| 3 | 1 | 5 | 9 |
修正后的需求
原本是对values列聚合填充,但现在values是分类类型,需要统计每个(index, columns)组合下,所有指定分类值的出现次数,格式类似9:2,10:0,11:0(假设分类取值固定为9、10、11)。
实现方案
这里分两步来实现:先分组统计每个组合的分类计数,再重塑成你要的宽表格式。
完整代码示例
import pandas as pd # 1. 初始化原始DataFrame test_df = pd.DataFrame({ "index":[1,2,3,1], "columns":[5,6,7,5], "values":[9,9,9,9] }) # 2. 定义所有需要统计的分类取值 target_categories = [9, 10, 11] # 3. 编写分组统计函数:统计每组内各分类的出现次数,转换成指定格式 def format_category_counts(group): # 统计当前组的value计数,缺失的分类用0填充 count_series = group["values"].value_counts().reindex(target_categories, fill_value=0) # 转换成"分类:次数"的字符串拼接格式 return ", ".join([f"{cat}:{count_series[cat]}" for cat in target_categories]) # 4. 按index和columns分组,应用统计函数 grouped_result = test_df.groupby(["index", "columns"]).apply(format_category_counts).reset_index(name="category_counts") # 5. 重塑为宽表:行是index值,列是columns值,填充统计结果 final_df = grouped_result.pivot(index="index", columns="columns", values="category_counts") # 可选:如果希望NaN显示为全0的统计字符串,而不是空值 default_count_str = ", ".join([f"{cat}:0" for cat in target_categories]) final_df = final_df.fillna(default_count_str) # 打印结果 print(final_df)
运行结果
如果不做fillna处理,输出是:
columns 5 6 7 index 1 9:2,10:0,11:0 NaN NaN 2 NaN 9:1,10:0,11:0 NaN 3 NaN NaN 9:1,10:0,11:0
如果加上fillna处理,输出会变成:
columns 5 6 7 index 1 9:2,10:0,11:0 9:0,10:0,11:0 9:0,10:0,11:0 2 9:0,10:0,11:0 9:1,10:0,11:0 9:0,10:0,11:0 3 9:0,10:0,11:0 9:0,10:0,11:0 9:1,10:0,11:0
关键说明
reindex(target_categories, fill_value=0)是核心:确保所有指定的分类都被统计到,哪怕该组里没有这个分类,也会显示0次。pivot方法用来把长表转换成你需要的宽表结构,行和列对应原始的index和columns列。- 如果你的分类取值有变化,只需要修改
target_categories列表即可,核心逻辑无需改动。
内容的提问来源于stack exchange,提问作者david
相关产品推荐
相关产品推荐

