
使用 `pd.cut` 对两列分别分箱,再通过 `pd.crosstab` 一键生成交叉频数表,可替代冗长的手动布尔索引计数逻辑,代码从数十行压缩为2行,兼具可读性与可维护性。
在数据分析中,常需根据多个数值列的组合条件对样本进行分类统计(例如:按 Age1 的区间 × Age2 的区间 统计频数)。原始方法依赖嵌套布尔索引和重复调用 len(),不仅代码冗长、易出错(如边界不一致、漏写括号),而且难以扩展或复用。
推荐采用 向量化分箱 + 交叉制表 的标准范式:
import pandas as pd
import numpy as np
data = pd.DataFrame({
'Age1': [45, 48, 52, 51, 48, 45, 62, 47, 65, 50],
'Age2': [37, 68, 71, 54, 67, 59, 95, 56, 41, 42]
})
# 定义统一区间:(-∞, 40], (40, 50], (50, 60], (60, ∞)
bins = [-np.inf, 40, 50, 60, np.inf]
# 一步生成二维频数表
result = pd.crosstab(
pd.cut(data['Age1'], bins=bins, right=True), # Age1 分箱(右闭区间)
pd.cut(data['Age2'], bins=bins, right=True) # Age2 分箱(右闭区间)
)
print(result)输出结果为清晰的交叉频数矩阵:
Age2 (-inf, 40.0] (40.0, 50.0] (50.0, 60.0] (60.0, inf] Age1 (40.0, 50.0] 1 1 2 2 (50.0, 60.0] 0 0 1 1 (60.0, inf] 0 1 0 1
✅ 优势说明:
- pd.cut 自动处理边界逻辑(right=True 表示右闭,默认行为),避免手动写 >=/
- pd.crosstab 天然支持分类型索引,结果直接可读、可导出、可可视化;
- 若需自定义行列标签(如 "40-50" 替代 (40.0, 50.0]),可在 pd.cut 中添加 labels 参数;
- 支持进一步聚合,如 .apply(lambda x: x / x.sum(), axis=1) 计算行百分比。
⚠️ 注意事项:
- 确保 bins 在两列中完全一致,以保证语义对齐;
- 若数据含缺失值(NaN),pd.cut 默认将其归为 NaN 类别,crosstab 会自动忽略(如需保留,设置 dropna=False);
- 如需严格匹配原题中的分类名称(60),可后续用 result.rename_axis 和 result.rename 重命名索引。
该方法是 Pandas 生态中处理“双维度区间计数”问题的标准、高效且可扩展的解决方案。








