一句话总结
pd.crosstab()用于计算两个或多个分类变量的频数交叉表(列联表),是pivot_table的便捷特化版本,也可计算占比、均值等聚合统计。
1. crosstab() 基本语法
pd.crosstab(index, columns, values=None, rownames=None, colnames=None,
aggfunc=None, margins=False, margins_name='All', dropna=True,
normalize=False, sort=True)参数详解
| 参数 | 说明 |
|---|---|
index | 行分组键:类数组、Series、列名列表等 |
columns | 列分组键:类数组、Series、列名列表等 |
values | 可选,用于聚合的数值数组/DataFrame 列 |
rownames | 行索引名称(当 index 为 Series/数组时设置) |
colnames | 列索引名称 |
aggfunc | 指定 values 后使用的聚合函数,如 'sum'、'mean'、np.mean |
margins | 是否添加总计行列,默认 False |
margins_name | 总计名称,默认 'All' |
dropna | 是否剔除全为 NaN 的行,默认 True |
normalize | 归一化:False(频数)、'all'(整体占比)、'index'(行占比)、'columns'(列占比)、True(等价 'all') |
sort | 是否对结果排序,默认 True |
与
pivot_table的关系当
crosstab()的values和aggfunc参数同时给出时,其行为等价于:df.pivot_table(index=index, columns=columns, values=values, aggfunc=aggfunc)区别在于
crosstab()可直接接收独立的 Series/数组作为输入,无需先在 DataFrame 中。
2. 基本示例
频数交叉表
import pandas as pd
df = pd.DataFrame({
'gender': ['男', '女', '男', '女', '男', '女'],
'grade': ['A', 'B', 'B', 'A', 'A', 'B'],
'score': [88, 76, 91, 85, 92, 79]
})
ct = pd.crosstab(df['gender'], df['grade'])
print(ct)
# grade A B
# gender
# 女 1 2
# 男 2 1多列交叉(行/列为列表)
# 行:gender;列:grade + score 分箱
pd.crosstab(df['gender'], [df['grade'], df['score']])添加名称 rownames / colnames
pd.crosstab(df['gender'], df['grade'],
rownames=['性别'], colnames=['成绩等级'])3. 带聚合的交叉表
使用 values + aggfunc
ct_mean = pd.crosstab(df['gender'], df['grade'],
values=df['score'], aggfunc='mean')
print(ct_mean)
# grade A B
# gender
# 女 85.0 77.5
# 男 90.0 91.0多个聚合函数
# 使用 aggfunc 字典(较新版本支持列表)
pd.crosstab(df['gender'], df['grade'],
values=df['score'], aggfunc='sum')4. normalize 归一化
# 整体占比
pd.crosstab(df['gender'], df['grade'], normalize='all')
# 每行占比(行归一化)
pd.crosstab(df['gender'], df['grade'], normalize='index')
# 每列占比(列归一化)
pd.crosstab(df['gender'], df['grade'], normalize='columns')5. margins 总计
pd.crosstab(df['gender'], df['grade'], margins=True, margins_name='合计')
# 在行尾和列尾添加"合计"6. 实战:多维度交叉分析
# 更复杂的数据
df2 = pd.DataFrame({
'department': ['技术', '技术', '市场', '市场', '技术', '市场'] * 2,
'level': ['初级', '高级', '初级', '高级', '中级', '中级'] * 2,
'satisfaction': ['高', '低', '高', '高', '中', '低'] * 2,
'salary': [8000, 15000, 7000, 16000, 11000, 9000] * 2
})
# 二维交叉:部门 × 级别 的满意度频数
cross1 = pd.crosstab(df2['department'], df2['level'])
# 三维交叉:部门 × (级别, 满意度)
cross2 = pd.crosstab(df2['department'], [df2['level'], df2['satisfaction']])
# 行占比 + 总计
cross3 = pd.crosstab(df2['department'], df2['level'],
normalize='index', margins=True)7. 注意事项
易错点
index和columns参数名是位置参数,第一个位置对应index,第二个对应columns。normalize与margins同时使用时,总计行列基于归一化后的数值。values+aggfunc若无匹配数据,结果会产生NaN,可用fillna(0)处理。
应用场景
- 探索性分析中快速了解两个分类变量的关系
- 数据质量检查:查看类别组合的覆盖情况
- 机器学习特征工程中生成交叉特征