# 图表 Gene Zelazny 在麦肯锡当视觉传达总监时写了《用图表说话》(Say It With Charts, 1985), 立下一条至今没被推翻的规矩:**先确定要传达的信息,再选图表形式**。 这份文件继承那条规矩,并且补上他那本书里没有的两件事: 用实证决定视觉编码,以及检查这张图有没有在误导人。 --- ## 一、第一步永远不是选图表 第一步是把要传达的信息写成一个**完整的句子**。 不是「各地区销售额」——那是主题,不是信息。 是「**华东贡献了六成销售额,但增速最慢**」——这是信息。 写不出这个句子,说明你还不知道要说什么,这时候画任何图都是在装饰数据。 写出来之后,这句话有两个用途:它决定图表类型(见下),并且**它就是图表的标题**。 ### 标题写结论,不写主题 | 别写 | 写 | |---|---| | 各渠道转化率对比 | 渠道 C 的转化率是其他渠道的三倍 | | 月度销售趋势 | 销售额连续五个月下滑,三月起跌幅扩大 | | 用户年龄分布 | 七成用户集中在 25–34 岁 | 读者看图的时间只有几秒。标题写主题,他得自己去找结论,多半找不到或找错。 标题写结论,图就成了证据。 **例外**:探索阶段自己看的图不需要结论标题——那时候你还不知道结论是什么, 硬写一个反而会让你只看见你想看见的。 --- ## 二、从信息里的关键词,推导比较类型 方法来自 Zelazny:**看你那句话里用了什么词**。骨架用 FT Visual Vocabulary 的九大类——它是这个行业的事实标准,也是唯一有官方中文译名的一套。 先定你要表达**哪一种关系**,再从那一类里挑图。跳过这一步直接选图, 选出来的永远是柱形、折线、饼这三个条件反射。 | 句子里出现 | 关系类型 | 首选图 | |---|---|---| | 高于/低于、超出、缺口、顺差逆差、正负 | **离差** Deviation | 分向条形图、**子弹图**(实绩 vs 目标)、赤字填充线图 | | 随着、与…有关、影响、相比之下 | **相关性** Correlation | 散点图、**链接散点图**(两变量随时间共同移动)、泡泡图 | | 大于、小于、排名、第一、最高 | **排序** Ranking | 排序条形图、**棒棒糖图**(类目多时更干净)、**凹凸线图**(排名随时间变) | | 集中、分布、范围、多少个落在、偏 | **分布** Distribution | 直方图、箱线图、**小提琴图**、**点状条纹图** | | 变化、增长、下降、趋势、波动 | **随时间的变化** | 折线图(点多)/柱形图(点少于 8)、**日历式热图**、**坡度图**(只有两期时的首选) | | 多大、多少、规模、总量 | **规模** Magnitude | 柱形图、成对柱形图、**比例符号图**、**象形符号**(科普类效果远超柱形) | | 占、份额、构成、其中、拆开 | **部分和整体** | 排序条形图、堆叠条、**Marimekko**(同时表达占比和绝对量)、树状图 | | 哪里、地区之间、分布在 | **地理空间** Spatial | 分级统计图、**点状密度地图**、**等高线地图**、均等化示意地图 | | 从 A 到 B、流向、转化、流失 | **流向** Flow | **桑基图**、漏斗图、**和弦图**、网络图、流向地图 | **两条容易踩反的判据:** **规模 vs 部分和整体。** 读者只关心「各个部分各自有多大」时,用规模类,别用堆叠—— 堆叠图的第二段之后没有共同基线,长度没法比。只有当「它们加起来是一个整体」 这件事本身是论点时,才用部分和整体类。 **规模类只用于数量,不用于比率。** 桶、人、美元、单量可以比大小; 百分比、转化率、中位数不行——它们的分母各不相同,画在一起等于让读者比较两个 不同的东西。这条同时也是加法的判据:**不能进同一个 sum() 的数,也不该进同一组柱子。** ### 九大类之外,这几类值得单列 它们在 FT 的框架里散落在几个大类下,但业务分析里出现频率高,单独记更好用: | 你要说的 | 图表 | |---|---| | 从起点到终点被哪几项吃掉了 | **瀑布图** | | 两组的分布形状不同 | 并排箱线图 / 小提琴图 / 重叠密度 | | 构成随时间变化 | 百分比堆叠面积图 | | 各批次随时间的留存 | 热力图(cohort 三角) | | 这个预测有多不确定 | 折线 + 置信带 / 扇形图 | | 很多个体各自怎么变的 | **小倍数图(small multiples)** | **完整的九大类 × 约 60 种图表**(含官方中文译名、每类的适用说明、 FT 自己用在什么题材上)见 FT 官方开源海报,中英文版都有: `github.com/Financial-Times/chart-doctor` → `visual-vocabulary/` (`Visual-vocabulary-cn-simplified.pdf` 是简体中文版)。 **选图卡住时去翻那张海报,比在这里列 60 行有用。** **瀑布图和坡度图被严重低估。** 「利润从 1200 万变成 900 万」——瀑布图能一眼说清这 300 万是被哪几项吃掉的, 这是任何柱状图做不到的。 两个时点、多个主体的对比,坡度图比并排柱状图清楚一个数量级, 因为交叉的线条直接把「谁反超了谁」画了出来。 **小倍数图是里面最被低估的一个。** 同一种图重复 N 次, 共享同一套坐标轴和量程,每一格只换一个变量(一个地区、一个指标、一个月份)。 它解决的是一个很常见的困境:你有 8 个指标要对比趋势, 塞进一张图是 8 条线的意大利面,分成 8 张独立的图读者又没法比较。 小倍数两头都占——因为**量程共享,跨格比较是合法的**; 因为**每格只有一条线,格内一眼看得清**。 Tufte 说过这种设计「一旦读者看懂了第一格,剩下的全部免费」。 代价只是每格变小,所以别标太多数字,一格留一个结论点。 用它的信号:你正想写「把这几条线画在一起有点乱」,或者正准备 给某张图加第二根 Y 轴——**那两种冲动都是小倍数图的入口**。 **它有一个专属的坑:每格的窗口边界要按业务事件切,不能图省事取固定长度。** 实测踩过——画「五条视频各自发布后 14 天的播放衰减」, 其中两条的 14 天窗口跨过了下一条视频的发布日, 于是下一条片的流量高峰长到了上一条片的曲线里, 图上凭空多出第二个尖峰,和图题「两三天后回落」直接矛盾。 固定窗口在多数场景没问题,但只要格与格之间的事件会互相污染 (连续发布、活动重叠、同一批用户经历多次干预), 就必须把每格截断到下一次事件之前。 截断后各格长度不同,横轴保持同一刻度、短的那格自然留白即可——跨格仍然可比。 **这类错误机器查不出来。** 渲染自检能告诉你线有没有画出框、标签有没有重叠, 但它不知道那根线里混进了不该有的数据——从像素上看,一根说谎的线和一根诚实的线 长得一模一样。唯一能抓到它的动作,是画完之后盯着图问一句: 它真的在说图题那句话吗? ### 基线图:报告开头那张,选哪个 上面整张菜单是按「你要说的那句话」来选的。但报告开头的基线层不为某句话服务, 它给读者建坐标系(为什么需要这一层 → SKILL.md「基线层」)。选型简单得多: | 数据形态 | 基线图 | 它一眼回答 | |---|---|---| | 若干主体,一个时点 | **排序条形图**,标绝对值和占比 | 有谁、谁最大、差距多大 | | 若干主体,随时间 | **堆叠柱/面积**(绝对值,不是百分比) | 构成怎么变的 + 总量怎么变的 | | 只关心构成不关心总量 | **百分比堆叠** | 份额此消彼长 | | 主体很多、长尾很长 | 排序条 + **累计占比线**(帕累托) | 集中度:前几名吃掉多少 | | 单一变量的个体分布 | **直方图 / 箱线图** | 典型值在哪、尾巴多长 | **默认选绝对值堆叠,不选百分比堆叠。** 百分比堆叠把总量拍平了, 读者看不出这个市场是在扩张还是萎缩——而那通常是他最先想知道的事。 需要看份额此消彼长时,再补一张百分比版本。 **基线图必须把玩家列全。** 排序条形图里的「其他」如果超过两成, 说明你的分类没做完,或者数据覆盖不全——**这时候要回头查数据,不是把它画出来了事。** 一份声称是市场份额的数据,画基线图时发现少了一个占两成的玩家, 那它就不是市场份额。这是画基线图最大的附带收益:**覆盖度问题只有在 你试图列全的时候才会暴露**,内部一致性检查(份额加总等于 100%)查不出来。 --- ## 三、为什么不用饼图:这不是审美之争 Cleveland 和 McGill 在 1984 年做了一个图形感知实验,测量人从不同视觉编码里 读出数量的准确度。结果是一个精度阶梯: ``` 1. 位置(共同基线) ← 最准 2. 位置(非对齐基线) 3. 长度、方向、角度 4. 面积 5. 体积、曲率 6. 明暗、色饱和度 ← 最不准 ``` 实测:位置判断比长度准 1.4–2.5 倍,比角度准 1.96 倍。 **条形图用「长度 + 共同基线」编码,饼图用「角度和面积」编码。** 所以同一份数据,读者从条形图里读出的数字更接近真实。这是有测量结果的, 不是「我觉得饼图丑」。 Zelazny 1985 年推荐用饼图表达成分关系时,这个实验才发表一年。今天我们有更好的选择。 **饼图仍然可用的唯一场景**:只有 2–3 个类别,而且只需要传达「大概一半」 「大概三分之一」这种粗略印象。超过 3 类,改用排序条形图。 **这个阶梯的其他用法**: - 要读者精确比较 → 用位置或长度(散点、条形) - 只需传达冷热模式 → 才用颜色(热力图) - **永远不要用面积编码数量**(气泡大小、面积图的宽度)——精度排第 4, 而且人普遍把面积差异读小(半径翻倍,面积是四倍,但看起来只像两倍多) --- ## 四、诚实性检查:一张图怎么在不撒谎的前提下误导人 这一节是 Zelazny 那本书里没有的。每张图交付前过一遍。 ### 1. Y 轴基线 **柱状图(含条形图)必须从 0 开始。** 柱子编码的是长度, 截断基线就打破了「柱高之差正比于数值之差」这个视觉约定。 把 Y 轴从 34% 开始,能把一个 2 个百分点的差异画成一倍的差距。 **折线图不必从 0。** 折线编码的是位置和斜率,不是长度。 强行从 0 开始会把真实的波动压成一条直线,那是另一种误导。 判断标准是**看这个图形用什么编码**,不是背「永远从 0」这条教条。 ### 2. 双 Y 轴 两条不同量纲的线画在同一个框里,**可以凭空造出一个并不存在的相关性**—— 调整任意一根轴的刻度,两条线就能贴合或分开,画图的人可以随意制造「同步」的假象。 替代方案:两张上下对齐的小图(共享 X 轴),或者把两个指标都转成指数(基期=100)。 要用双轴,必须在图上说明两根轴的刻度是人为选定的。 ### 3. 时间窗口 起点和终点选在哪里,能得出完全相反的结论。 起点必须有业务理由(财年初、改版日、活动开始),不能是「从这里开始看最好看」。 ### 4. 不完整的最后一期 本月只过了 12 天,月度柱状图的最后一根必然矮一截,看起来像断崖下跌。 **不完整的期次要么去掉,要么用虚线/浅色明确标注。** 这是所有图表错误里最常见、最容易被原谅、也最误导人的一个。 ### 5. 颜色暗示因果和情绪 红色=坏、绿色=好,这个映射会绕过读者的理性判断。 「退货率上升」标红没问题,但「某个渠道占比高」标红就是在下判断而不是呈现事实。 同理:不要用颜色深浅表示「重要性」,那是你的判断不是数据。 ### 6. 排序即观点 条形图按什么排序,就在暗示什么。按值排序是中性的; 按你想强调的项目排在最上面,是在引导。至少要让读者知道排序规则。 ### 7. 面积和图标缩放 用图标大小表示数量时,如果同时缩放宽和高,数值翻倍会让面积变成四倍。 **只缩放一个维度,或者干脆别用。** ### 8. 只给导出量,不给水平量 这一条最隐蔽,因为图本身完全准确。 差值、增量、比率、指数都是导出量。它们把两个(或多个)水平量压成一个数, 压缩过程中丢掉的信息读者还原不回来: - 一条停在「+27.4 个百分点」的线,可能是 63 比 36,也可能是 90 比 63 - 一张只画增量的瀑布图,说清了多出来的钱去了哪, 但读者不知道原来那个盘子由什么构成、最大的一块占多少 - 一条指数化到 100 的线涨到 263,读者不知道起点是每人每月 4 美元还是 4 万 为什么偏偏是这类图最容易被选中?因为你问的是「哪张图最能证明我这句话」, 而导出量本身就是那句话。水平量图不证明任何东西,于是第一轮就被淘汰了。 换句话说,出问题的是筛选规则本身,不是你的判断力—— 你每一次都选得很对,只是那个问题问错了。 修法不是不画导出量,它们通常确实是最有力的论证图; 而是在它前面补一张能读出水平量的图。版面只够一张时画水平量, 把导出量写进图题(「教育一家占三成」比「教育贡献了 34% 的增量」信息量大, 因为前者能推出后者的量级,反过来不行)。 --- ## 五、做工 **去掉不承载信息的墨水。**(Tufte 的 data-ink ratio) 网格线淡化或删掉、去掉图表边框、去掉背景色、去掉 3D 效果、去掉阴影。 3D 柱状图在任何情况下都是错的——它引入了透视失真,让前排的柱子看起来更大。 **用直接标注代替图例。** 图例强迫读者在颜色和标签之间来回扫视。把标签直接放在线的末端或柱子上, 读者的眼睛不用跑。这一条对提升可读性的效果超过其他所有技巧。 **只标关键数据点。** 每根柱子都标数字,等于没有重点,而且那时候你需要的是表格不是图。 标最高、最低、和你要讲的那一个。 **类别名长就用横向条形图。** 竖着的柱状图遇到「华东大区直营门店」这种标签,只能斜着写或者截断,两种都难读。 **排序。** 类别没有内在顺序时(地区、渠道、产品),一律按值排序。 按字母或按原表顺序排列,读者得自己在脑子里排一遍。 有内在顺序时(月份、年龄段、满意度等级)保持原顺序,不要按值排。 **色板。** - 分类数据:不同色相,**最多 6 类**,超过就合并成「其他」 - 连续数据:单一色相的深浅渐变,不要用彩虹色阶 (彩虹色阶在感知上不是均匀的,会在黄色附近造出并不存在的边界) - 有正负之分:双色发散色板,中点是 0 - **色盲友好**:约 8% 的男性有红绿色觉障碍。红绿对比是最常用也最糟的选择, 改用蓝橙。或者除了颜色再加一个区分维度(形状、虚实线、直接标注) - 灰度打印测试:把图转成灰度还能不能区分?能,说明不只靠颜色传达信息 **焦点色:上色之前,先找到那个真实的二分。** 多数图不需要六个分类色,只需要一个——但**不是「把重要的那条涂红」**。 那是在用颜色表达你的判断,`report-styles.md` 第六节和本文件第四节第 5 小节都禁止, 而且它没有可复制的判据:什么算重要? 成立的用法是:**被涂色的那一半,本身有一条数据里就存在的分界线。** | 分界线 | 例子 | |---|---| | 时间上的前 / 后 | 2025/07 之前是灰的,之后是红的——分界点是那场发布会 | | 归属上的是 / 否 | HBM 涂红、其他 DRAM 留灰——分界是产品类别 | | 口径上的实际 / 预计 | 只有最后一根柱子是红的,因为它是预测值 | 读者看到的「重点」是这个分界的**结果**,不是你替他做的判断。 找不到这样一条分界线,就说明这份数据没有焦点——那就老实按分类色板来, 或者全部用中性灰。 配套三条: - 底色数据走中性灰,焦点色**从分类色板里取最饱和的那个**—— 不占强调色的位子(`report-styles.md` 第六节:强调色不用于数据) - 最多再加一个「另一半」的对照色,用来画变化前的那一侧 - **一页两个焦点色,等于没有焦点** **末端直标要带数值,数值用该系列的色。** 「英伟达 66.2%」直接写在绿线的末端,「苹果 32.6%」写在红线的末端。 名字和数字一次给全,读者不用回头去纵轴上找。 数值必须用表格数字,否则几条线末端的数字会左右参差。 **中文排版**:图表里的中文标签不要竖排,不要用中英文混排的长标题。 数字用等宽或表格数字(tabular figures),让小数点对齐。 --- ## 六、什么时候不该画图 **一个数字不需要图。** 「转化率是 3.2%」就写这句话,加大加粗。 一根孤零零的柱子不传达任何比较信息。 **两三个数字用句子。** 「A 是 120,B 是 95」比一张两根柱子的图快得多。 **要精确查值用表格。** 图擅长表达模式和比较,不擅长让人读出精确数字。 读者要查「三月华东具体多少」,给表格。 **没有信息就别画。** 如果你写不出那个结论句子,这张图就是装饰。 报告里每多一张没有结论的图,读者对整份报告的信任就少一分。 **类别超过 15 个**,图会变成一片噪音。要么聚合成大类,要么给表格, 要么只画 Top 10 + 其他。 --- ## 七、生成 Excel 原生图表 用 `scripts/make_chart.py`,它会先按上面的规则**建议图表类型**,再生成。 ```bash # 让它推荐 python3 scripts/make_chart.py data.xlsx --suggest # 生成(图表嵌进 xlsx,可继续编辑) python3 scripts/make_chart.py data.xlsx --x 门店 --y 销售额 \ --title "深圳南山店销售额领先第二名 20%" --out chart.xlsx ``` **为什么生成 Excel 原生图表而不是图片**: 交出去的是活的。用户改数据图会自己更新,能调格式,能复制进 PPT 保持矢量。 一张 PNG 是死的,而且改一个数就得回来找你。 需要静态图片或复杂图形(桑基、热力图)时,用 Python 绘图库另出, 但**默认应该是原生图表**。 --- ## 八、把上限往高处推 前七节讲的是「不要画错」。这一节讲「不要停在条件反射上」—— 它不限制你画什么,只保证你遍历过可能性。 **先校准一下什么叫「野心」。** 行业年度评选(Pudding Cup 这类)的获奖作品, 几乎全是**一个具体问题讲到底**——选题小、挖得深、交互只服务于理解。 一个都不是「数据大屏」型。所以野心不是把图做复杂、把指标堆满, 是把一句话讲得让人无法反驳。**加一个交互之前先问:它帮读者理解了什么, 还是只证明了我会做交互?** **先问能不能画,再动笔写。** 每要下一个结论,先问「这句话能不能变成一张图」。 文字是图画不出来时的退路,不是默认选项。一屏全是字,说明该看的东西都埋在段落里了。 **图是论证,不是插图。** 每张图必须能独立回答它标题里那句话—— 读者只看图和图题就该得到那个结论。做不到,它就是装饰,删掉。 **你第一时间想到的图,通常不是最好的那张。** 柱形、折线、饼是三个条件反射。 第二节那张比较类型表列了十几种——瀑布、坡度、哑铃、cohort 热力、小倍数、 分布对比、百分比堆叠面积。**动笔前把它过一遍。** 最后仍然选柱状图完全没问题, 但那要是「看过菜单之后的选择」,不是「只认识这三个」。 **小倍数图(small multiples)是被低估最厉害的一个。** 同一种图重复 N 次、共享坐标轴、每格只换一个变量。多指标同期对比、 多分组同一趋势,它比「把所有线塞进一张图」清楚一个数量级。 **一段话如果在解释旁边那张图,删掉它——改进图题。** 这是控制文字量最有效的一刀。图和图题应当自足;需要一段正文来讲图上发生了什么, 说明图没画好,或者图题写的是主题不是结论。 正文只该讲图表达不了的东西:为什么、所以呢、这里有什么坑。 **版面上最大的东西,应该是最重要的东西。** 字号、色块面积、留白、位置都在替你给信息排序,读者会照着这个序读。 排完回头看:视觉权重最高的三样,是不是就是最想让他记住的三件事?不是就重排。 这比配色重要得多。 **交付时说一句你考虑过但没用的图表形式,以及为什么。** 一两句就够。写不出来,说明没有真的遍历过可能性。 ### 手写 SVG 最常撞的三个闸门 FAIL 事先写死就能避免,不用等 `verify_visual.py` 报了再返工: | 症状 | 根因 | 预防写法 | |---|---|---| | 图例超出 viewBox | 图例行数增加了,画布高度没跟着加 | 图例行数变化时同步重算 viewBox 高度,别写死 | | 最右侧数据标签溢出画布 | 标签锚点固定在数据点右侧 | 夹取 x 坐标,接近右边界时改 `text-anchor="end"` 或走折线引线 | | 差值文字与轴标签重叠 | 两者都贴着格子底部 | 差值文字放格子顶部,或给轴标签留出固定高度的保留区 | 另外:`` 是非法属性——图会照常渲染,但控制台报错, 肉眼完全看不出来。高度要么写具体值,要么靠 `viewBox` + CSS 控制。