
本文介绍如何利用 pd.crosstab 将长格式的分类评分数据(如 high/medium/low)高效转换为按分组(如店铺)展开的宽表,自动生成对应类别的计数列,并控制类别顺序与轴标签。
本文介绍如何利用 pd.crosstab 将长格式的分类评分数据(如 high/medium/low)高效转换为按分组(如店铺)展开的宽表,自动生成对应类别的计数列,并控制类别顺序与轴标签。
在数据分析中,常需将“长格式”(long format)的分组-类别记录(例如每条记录代表某店铺的一次顾客评分)聚合为“宽格式”(wide format)的汇总表——即每个唯一分组(如 Shop)作为一行,每个预定义类别(如 'High'、'Medium'、'Low')作为一列,单元格值为该店铺获得该评分的总次数。这种结构更便于后续统计、可视化或建模。
pandas 提供了专为此类任务设计的高效函数:pd.crosstab。它本质是二维频数表生成器,支持索引(行分组)、列变量(类别维度)及可选的值聚合逻辑。为确保输出列严格按指定顺序(如 High → Medium → Low),推荐先将目标列转为有序分类类型(pd.Categorical),再传入 crosstab:
import pandas as pd # 原始数据:长格式,含重复店铺ID data = [['store1', 'High'], ['store1', 'Medium'], ['store2', 'Low'], ['store2', 'Low']] df = pd.DataFrame(data, columns=['Shop', 'Review']) # 步骤1:将 Review 列设为有序分类,明确指定类别顺序 df['Review'] = pd.Categorical(df['Review'], categories=['High', 'Medium', 'Low']) # 步骤2:生成交叉表(行=Shop,列=Review) result = pd.crosstab(df['Shop'], df['Review']) print(result)
输出:
Review High Medium Low Shop store1 1 1 0 store2 0 0 2
默认情况下,crosstab 会为行索引和列名添加轴标签(如 Shop 和 Review)。若需更简洁的表格结构(例如直接用于导出或合并),可链式调用 rename_axis 清除这些标签:
result_clean = pd.crosstab(df['Shop'], df['Review']).rename_axis(index=None, columns=None) print(result_clean)
输出:
High Medium Low store1 1 1 0 store2 0 0 2
✅ 关键注意事项:
- 若不设置 categories,crosstab 仅生成实际出现的类别列(如缺失 'Medium' 则不会创建该列),可能导致列结构不稳定;显式声明类别可保障输出一致性,尤其适用于批量处理或下游系统对接。
- crosstab 返回的是 DataFrame,其索引为分组字段(Shop),可直接与原表通过 join 或 merge 关联,也可重置索引(.reset_index())以转为普通列。
- 对于更复杂的聚合需求(如同时统计均值、最大值),可考虑 pivot_table,但纯频数统计场景下 crosstab 更简洁、语义更清晰。
掌握此方法,即可在单行核心代码内完成从细粒度行为记录到结构化汇总表的转化,显著提升数据预处理效率。

















