本文介绍使用 pandas 的 pd.crosstab 配合 normalize='columns' 快速生成按城市-月份分组的 Visa 销售额占比表,避免手动计算分母,实现类似 DAX 中“% of Column Total”的效果。
本文介绍使用 pandas 的 `pd.crosstab` 配合 `normalize='columns'` 快速生成按城市-月份分组的 visa 销售额占比表,避免手动计算分母,实现类似 dax 中“% of column total”的效果。
在数据分析中,常需将原始交易数据转换为“某维度(如支付方式)在另一组交叉维度(如城市 × 月份)中的占比”。与 Excel 或 Power BI 中通过 DAX 创建动态度量不同,pandas 需借助结构化聚合与归一化机制实现同等效果。核心在于:占比必须基于每个(City, Month)组合下的全部支付金额(Visa + MasterCard)作为分母,而非全局或行/列总和。
以下为完整、可复现的解决方案:
import pandas as pd
# 构造示例数据
data = {
'Month': ['Jan', 'Jan', 'Jan', 'Jan', 'Feb', 'Feb', 'Feb', 'Feb', 'Feb'],
'City': ['Paris', 'Paris', 'London', 'London', 'Paris', 'Paris', 'London', 'London', 'Paris'],
'Card': ['Visa', 'MasterCard', 'Visa', 'MasterCard', 'Visa', 'MasterCard', 'Visa', 'MasterCard', 'Visa'],
' Amount ': [' $101 ', ' $567 ', ' $447 ', ' $446 ', ' $926 ', ' $652 ', ' $114 ', ' $88 ', ' $408 ']
}
df = pd.DataFrame(data)
# 步骤 1:清洗金额列(去除空格与美元符号,转为整数)
df[' Amount '] = df[' Amount '].str.strip().str.replace(r'[$\s]', '', regex=True).astype(int)
# 步骤 2:使用 crosstab 构建多级列透视表,并按列归一化(即每列独立除以其列和)
ct = pd.crosstab(
index=df['Card'],
columns=[df['City'], df['Month']],
values=df[' Amount '],
aggfunc='sum',
normalize='columns' # ✅ 关键:对每个 (City, Month) 组合内的 Card 值归一化
)
# 步骤 3:重塑结构——将 City 提升为行索引,筛选 Visa 行,按指定月份排序
result = (
ct.stack(level='City', future_stack=True) # 将 City 列级转为行索引
.loc['Visa', ['Jan', 'Feb']] # 只取 Visa 行,并固定列顺序
.mul(100) # 转换为百分比
.round(2) # 可选:保留两位小数提升可读性
)
print(result)
输出结果:
Month Jan Feb City London 50.06 56.44 Paris 15.12 67.17
? 关键原理说明:normalize='columns' 并非对整个 DataFrame 的列求和,而是对 crosstab 输出中每个最细粒度列(即每个 (City, Month) 元组)单独归一化。例如,('London', 'Feb') 列下 Visa=114、MasterCard=88,其列和为 202 → Visa 占比 = 114 / 202 ≈ 56.44%。这正是业务所需的“Visa 占当月该城市总销售额的比例”。
注意事项:
- 若原始数据含缺失值或非数值金额,务必在 astype(int) 前做健壮清洗(如 pd.to_numeric(..., errors='coerce'));
- stack(level='City') 要求列索引为 MultiIndex,且 'City' 必须是其一级名称(可通过 ct.columns.names 确认);
- future_stack=True 是 pandas 2.1+ 推荐参数,兼容未来版本行为;旧版本可省略;
- 如需扩展至更多卡类型(如 Amex),无需修改逻辑,crosstab 会自动处理所有唯一值。
此方法简洁、向量化、语义清晰,是 pandas 中替代 DAX “% of Column Total” 度量的标准实践。










