5-3 透视表与交叉表的报告单


文档摘要

5-3 透视表与交叉表:报告的排版工序 本节摘要:pivottable把长表转成行列双维的横排报告,crosstab专做频次交叉,melt负责把宽表摊回长表。本节的核心是理解长宽两种数据形态的互换,这是报告排版与下游建模之间的摆渡船。 会诊指标算出来了(5-2),但那还是"每行一个门店"的长条表。管理层习惯看的是横排版:门店做行、渠道做列、格子里的金额。排版这道工序,就是长宽表的互换。 pivottable:两维排版的会诊报告 三个关键参数:margins补合计行、fillvalue补缺格、aggfunc换指标: ⚠️ 常见坑:pivottable的aggfunc默认是mean不是sum,而且不告警。

5-3 透视表与交叉表:报告的排版工序

本节摘要:pivot_table把长表转成行列双维的横排报告,crosstab专做频次交叉,melt负责把宽表摊回长表。本节的核心是理解长宽两种数据形态的互换,这是报告排版与下游建模之间的摆渡船。

会诊指标算出来了(5-2),但那还是"每行一个门店"的长条表。管理层习惯看的是横排版:门店做行、渠道做列、格子里的金额。排版这道工序,就是长宽表的互换。

pivot_table:两维排版的会诊报告

import pandas as pd df = pd.DataFrame({ '门店': ['A', 'A', 'B', 'B', 'C', 'A', 'B', 'C'], '渠道': ['线上', '线下', '线上', '线上', '线下', '线上', '线下', '线上'], '月份': ['1月'] * 4 + ['1月'] * 2 + ['2月'] * 2, '金额': [1280, 960, 1732, 880, 2100, 1150, 990, 860], }) # 行=门店 列=渠道 值=金额和 report = df.pivot_table(index='门店', columns='渠道', values='金额', aggfunc='sum') print(report) # 渠道 线上 线下 # 门店 # A 2430 960.0 # B 1732 990.0 # C NaN 2100.0 ← C线上没开张

三个关键参数:margins补合计行、fill_value补缺格、aggfunc换指标:

print(df.pivot_table(index='门店', columns='渠道', values='金额', aggfunc='sum', margins=True, margins_name='合计', fill_value=0)) # 渠道 线上 线下 合计 # 门店 # A 2430 960 3390 # B 1732 990 2722 # C 0 2100 2100 # 合计 4162 4050 8212

⚠️ 常见坑:pivot_table的aggfunc默认是mean不是sum,而且不告警。金额透视忘了写aggfunc='sum',报告里的数全成了均值——这是新手透视表事故的第一名。另外它的近亲pivot(无聚合版)要求行列组合唯一,有重复就抛错,遇到时说明该聚合了。

三维:行列再加层

# 月份塞进列的上一层,一张表装下两个月 wide = df.pivot_table(index='门店', columns=['月份', '渠道'], values='金额', aggfunc='sum', fill_value=0) print(wide) # 月份 1月 2月 # 渠道 线上 线下 线上 线下 # 门店 # A 1280 960 1150 0 # B 2612 0 0 990 # C 0 2100 0 860

列变成多层索引——第02章2-3的分层知识在此兑现:wide['1月']直接取整个月块,wide.loc[:, ('1月', '线上')]定位单列。

crosstab:数人头专用

# 不填values时,crosstab数的是频次:每类组合几条记录 print(pd.crosstab(df['门店'], df['渠道'])) # 渠道 线上 线下 # 门店 # A 2 1 # B 1 1 # C 1 1 # normalize='index':行内占比,一眼看出渠道结构 print(pd.crosstab(df['门店'], df['渠道'], normalize='index').round(2)) # 渠道 线上 线下 # 门店 # A 0.67 0.33 # B 0.50 0.50 # C 0.50 0.50

crosstab本质是"透视表数频次"的快捷方式,渠道结构、转化漏斗这类"看构成"的报告用它最快。

melt:宽表摊回长表

下游的绘图库与建模管线大多吃长表(每行一个观测),报告给人看是宽表,两者之间靠melt摆渡:

long = wide.reset_index().melt(id_vars='门店', var_name=['月份', '渠道'], value_name='金额') print(long.head(4)) # 门店 月份 渠道 金额 # 0 A 1月 线上 1280 # 1 B 1月 线上 2612 # 2 C 1月 线上 0 # 3 A 1月 线下 960

长宽表的摆渡关系

长表与宽表的双向摆渡

长表与宽表的双向摆渡

本节要点回顾

排版工序的最后一条经验:透视出的报告表在交付前补两个动作——给索引与列名起有业务含义的名字(rename_axis),以及把关键数字round到位数。机器不在乎这些,看报告的人在乎,而报告的最终读者永远是人。

  • pivot_table三参数:aggfunc显式写sum(默认mean是事故源)、margins补合计、fill_value补缺格
  • 多维排版产生多层列,分层取数是2-3知识的兑现
  • crosstab数频次,normalize看构成占比
  • melt是逆工序,报告宽表摊回明细长表喂给机器
  • 长宽各有归宿:存档用长表、汇报用宽表,来回摆渡别怕

追问:透视表的格子数为什么会骗人

一张大透视表看着信息量大,但格子越多、每格样本越少,数字越不可信。门店乘渠道乘月份,三维一上,几十行的数据摊到上百个格子里,大半格子是小样本或空格。排版前先做一道算术:总记录数除以格子数,平均每格不到五条的透视表不值得给管理层看。要么降维(先只看门店乘渠道),要么先filter掉小样本组(上一节的器械),要么在格子里放count让人看见样本量。报表的美德是诚实,不是密集。

# 在报告里附上样本量,让读者自己判断可信度 counts = df.pivot_table(index='门店', columns='渠道', values='金额', aggfunc='count', fill_value=0) print(counts) # 渠道 线上 线下 # 门店 # A 2 1 # B 1 1 # C 1 1

金额表配样本量表,两张一起出,这是我在实战里固定的报告姿势。

单表报告到此完工。下一章把订单、会员、门店多张表归并成一份完整病史。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U