现在位置: 首页 > Pandas 教程 > 正文

Pandas pd.crosstab() 函数

Pandas 常用函数 Pandas 常用函数


pd.crosstab() 是 Pandas 库中用于计算交叉表(Cross Tabulation)的函数。它可以计算两个或多个变量的频次或聚合统计,生成类似 Excel 数据透视表的表格。

交叉表是统计分析中非常有用的工具,常用于分析两个或多个分类变量之间的关系,例如统计不同部门的男女员工数量。

单词释义crosstab 是 "cross tabulation"(交叉表)的缩写,是一种统计表格,展示两个或多个变量的联合分布。


基本语法与参数

pd.crosstab() 是 Pandas 库的顶级函数,用于计算交叉表。

语法格式

pd.crosstab(index, columns, values=None, aggfunc=None, margins=False, margins_name='All', dropna=True, normalize=False)

参数说明

  • 参数index
    • 类型: 数组-like、Series 或列表。
    • 描述: 用作行索引的数据。可以是单个列或多个列(列表)。
  • 参数columns
    • 类型: 数组-like、Series 或列表。
    • 描述: 用作列索引的数据。可以是单个列或多个列(列表)。
  • 参数values
    • 类型: 数组-like 或 None。
    • 描述: 要聚合的值。如果指定,则需要配合 aggfunc 参数使用。
  • 参数aggfunc
    • 类型: 函数或字符串。
    • 描述: 聚合函数(如 'sum', 'mean', 'count' 等)。当指定 values 时需要使用。
  • 参数margins
    • 类型: 布尔值。
    • 描述: 如果为 True,添加行列合计。默认为 False
  • 参数normalize
    • 类型: 布尔值或 'all', 'index', 'columns'。
    • 描述: 如果为 True,将值除以总计,生成比例(0-1)。也可以指定 'index' 或 'columns' 按行或按列归一化。

函数说明

  • 返回值: 返回一个 DataFrame,表示两个或多个变量之间的交叉关系。
  • 效果: 生成一个表格,行和列分别代表不同的分类变量,单元格显示对应的频次或聚合值。

实例

让我们通过一系列从简单到复杂的例子,彻底掌握 pd.crosstab() 的用法。

示例 1:基础用法 - 两个分类变量的交叉表

实例

import pandas as pd

# 1. 创建员工数据
employees = pd.DataFrame({
    'department': ['Sales', 'Sales', 'Sales', 'Engineering', 'Engineering', 'HR', 'HR', 'Sales', 'Engineering', 'HR'],
    'gender': ['Male', 'Female', 'Female', 'Male', 'Male', 'Female', 'Male', 'Female', 'Female', 'Male']
})

print("=== 员工数据 ===")
print(employees)

# 2. 计算部门与性别的交叉表(频次)
result = pd.crosstab(employees['department'], employees['gender'])
print("n=== pd.crosstab() 部门与性别交叉表 ===")
print(result)

运行结果预期:

=== 员工数据 ===
   department  gender
0        Sales    Male
1        Sales  Female
2        Sales  Female
3  Engineering    Male
4  Engineering    Male
5           HR  Female
6           HR    Male
7        Sales  Female
8  Engineering  Female
9           HR    Male

=== pd.crosstab() 部门与性别交叉表 ===
gender        Female  Male
department
Engineering        1     2
HR                 1     2
Sales              3     1

代码解析:

  1. 结果表格展示了每个部门中男性和女性的员工数量。

示例 2:添加行列合计和归一化

使用 margins 参数可以添加合计,normalize 参数可以查看比例分布。

实例

import pandas as pd

# 使用上面的员工数据
employees = pd.DataFrame({
    'department': ['Sales', 'Sales', 'Sales', 'Engineering', 'Engineering', 'HR', 'HR', 'Sales', 'Engineering', 'HR'],
    'gender': ['Male', 'Female', 'Female', 'Male', 'Male', 'Female', 'Male', 'Female', 'Female', 'Male']
})

# 1. 添加行列合计
result_margins = pd.crosstab(employees['department'], employees['gender'], margins=True)
print("=== 添加合计 (margins=True) ===")
print(result_margins)

# 2. 归一化 - 转换为比例
print("n=== 整体归一化 (normalize=True) ===")
result_norm = pd.crosstab(employees['department'], employees['gender'], normalize=True)
print(result_norm.round(3))

# 3. 按行归一化(每行加和为 1)
print("n=== 按行归一化 (normalize='index') ===")
result_norm_index = pd.crosstab(employees['department'], employees['gender'], normalize='index')
print(result_norm_index.round(3))

# 4. 按列归一化(每列加和为 1)
print("n=== 按列归一化 (normalize='columns') ===")
result_norm_col = pd.crosstab(employees['department'], employees['gender'], normalize='columns')
print(result_norm_col.round(3))

运行结果预期:

=== 添加合计 (margins=True) ===
gender        Female  Male  All
department
Engineering        1     2    3
HR                 1     2    3
Sales              3     1    4
All                5     5   10

=== 整体归一化 (normalize=True) ===
gender            Female  Male
department
Engineering      0.1   0.2
HR               0.1   0.2
Sales            0.3   0.1

=== 按行归一化 (normalize='index') ===
gender            Female  Male
department
Engineering    0.333   0.667
HR               0.333   0.667
Sales              0.75   0.25

=== 按列归一化 (normalize='columns') ===
gender            Female  Male
department
Engineering          0.2   0.4
HR                   0.2   0.4
Sales                0.6   0.2

代码解析:

  • 归一化方便分析比例关系,了解各部门中性别的相对分布。
  • 按行归一化显示每个部门中性别的百分比分布。
  • 按列归一化显示每个性别在各部门的分布比例。

示例 3:多个变量和聚合函数

可以使用多个行/列变量,并使用聚合函数计算统计值。

实例

import pandas as pd
import numpy as np

# 1. 创建销售数据
sales = pd.DataFrame({
    'region': ['North', 'North', 'South', 'South', 'East', 'East', 'West', 'West', 'North', 'South'],
    'product': ['A', 'B', 'A', 'B', 'A', 'B', 'A', 'B', 'B', 'A'],
    'quarter': ['Q1', 'Q1', 'Q1', 'Q1', 'Q2', 'Q2', 'Q2', 'Q2', 'Q2', 'Q2'],
    'sales': [100, 150, 200, 180, 120, 160, 190, 170, 140, 210]
})

print("=== 销售数据 ===")
print(sales)

# 2. 使用多个行变量
print("n=== 区域和产品的交叉表(频次)===")
result_multi = pd.crosstab([sales['region'], sales['product']], sales['quarter'])
print(result_multi)

# 3. 使用 values 和 aggfunc 计算销售额
print("n=== 区域和季度的销售额合计 ===")
result_sum = pd.crosstab(sales['region'], sales['quarter'], values=sales['sales'], aggfunc='sum')
print(result_sum)

# 4. 计算平均销售额
print("n=== 区域和季度的平均销售额 ===")
result_mean = pd.crosstab(sales['region'], sales['quarter'], values=sales['sales'], aggfunc='mean')
print(result_mean.round(1))

运行结果预期:

=== 销售数据 ===
   region product quarter  sales
0   North       A      Q1    100
1   North       B      Q1    150
2   South       A      Q1    200
3   South       B      Q1    180
4    East       A      Q2    120
5    East       B      Q2    160
6    West       A      Q2    190
7    West       B      Q2    170
8   North       B      Q2    140
9   South       A      Q2    210

=== 区域和产品的交叉表(频次)===
quarter               Q1  Q2
region product
East   A               0   1
       B               0   1
North  A               1   0
       B               1   1
South  A               1   1
       B               1   0
West   A               0   1
       B               0   1

=== 区域和季度的销售额合计 ===
quarter    Q1    Q2
region
East     NaN  280
North   250   140
South   380   210
West     NaN  360

=== 区域和季度的平均销售额 ===
quarter    Q1    Q2
region
East     NaN  140.0
North   125.0   140.0
South   190.0  210.0
West     NaN  180.0

代码解析:

  • 使用多个行变量(列表形式)可以创建多层索引的交叉表。
  • 每个单元格显示特定区域和产品组合在特定季度的出现次数。
  • 使用 values 和 aggfunc 参数可以计算实际数值的聚合(求和、平均等)。

示例 4:处理缺失值

dropna 参数控制是否包含缺失类别。

实例

import pandas as pd
import numpy as np

# 1. 包含缺失值的数据
data = pd.DataFrame({
    'A': ['a', 'a', 'b', np.nan, 'a', 'b'],
    'B': ['x', 'y', 'x', 'x', np.nan, 'y']
})

print("=== 包含缺失值的数据 ===")
print(data)

# 2. 默认移除包含缺失值的组合
result_drop = pd.crosstab(data['A'], data['B'])
print("n=== 默认移除缺失值 (dropna=True) ===")
print(result_drop)

# 3. 包含缺失类别
result_keep = pd.crosstab(data['A'], data['B'], dropna=False)
print("n=== 包含缺失类别 (dropna=False) ===")
print(result_keep)

运行结果预期:

=== 包含缺失值的数据 ===
     A    B
0    a    x
1    a    y
2    b    x
3  NaN    x
4    a  NaN
5    b    y

=== 默认移除缺失值 (dropna=True) ===
B    x  y
A
a    1  1
b    1  1

=== 包含缺失值 (dropna=False) ===
B      x    y  NaN
A
a      1    1    1
b      1    1    0
NaN    1    0    0

代码解析:

  • 默认 dropna=True 会移除包含缺失值的行和列,只显示有效数据。
  • 使用 dropna=False 可以查看包含缺失值的组合频次。

提示: pd.crosstab() 适合分析分类变量之间的关系。如果需要更复杂的数据汇总(如计算多个聚合指标),请使用 pd.pivot_table() 函数。

Pandas 常用函数 Pandas 常用函数