跳到主要内容

可视化设计原则

问题

如何设计一张好的数据图表?有哪些核心的可视化设计原则?

答案

核心原则

1. 数据墨水比(Data-Ink Ratio)

Edward Tufte 提出:图表中用于表达数据的"墨水"占总"墨水"的比例应尽量大。

Data-Ink Ratio=数据墨水总墨水\text{Data-Ink Ratio} = \frac{\text{数据墨水}}{\text{总墨水}}

实践

  • ✅ 去掉不必要的边框、网格线、背景色
  • ✅ 去掉图表垃圾(chartjunk):3D 效果、装饰性图案
  • ✅ 数据直接标注在数据点旁,减少读者查图例的负担
  • ❌ 不要为了美观添加无信息量的视觉元素

2. 视觉编码优先级

人眼对不同视觉编码的感知精度排序:

精度排名编码方式适用数据
1(最精确)位置散点图 X/Y
2长度柱状图高度
3角度/斜率折线图斜率
4面积气泡图大小
5颜色深浅热力图
6(最不精确)颜色类型分类区分
设计启示
  • 最重要的数据用位置和长度编码(柱状图、折线图)
  • 次要的维度用颜色编码
  • 避免用面积/体积精确比较数据(人脑对面积感知差)

3. 色彩使用规范

数据类型调色板类型示例
分类(渠道、产品线)定性调色板Tableau 10、Set2
连续(温度、收入)渐变调色板viridis、Blues
发散(增减、正负)发散调色板RdBu、coolwarm
色彩使用示例
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np

fig, axes = plt.subplots(1, 3, figsize=(15, 4))

# 定性(分类)
colors = sns.color_palette('Set2', 5)
axes[0].bar(range(5), [30, 25, 20, 15, 10], color=colors)
axes[0].set_title('定性调色板(分类)')

# 连续(渐变)
data = np.random.rand(5, 5)
sns.heatmap(data, cmap='YlOrRd', ax=axes[1], cbar_kws={'label': '值'})
axes[1].set_title('连续调色板(渐变)')

# 发散(正负对比)
data2 = np.random.randn(5, 5)
sns.heatmap(data2, cmap='RdBu_r', center=0, ax=axes[2])
axes[2].set_title('发散调色板(正负)')

plt.tight_layout()
plt.show()
色彩注意事项
  • 全球约 8% 男性有色觉障碍,避免红绿直接对比
  • 推荐使用 viridis(色盲友好 + 灰度打印友好)
  • 同一看板中颜色语义统一(红=警告/下降,绿=正常/增长)

4. 文字与标注

元素规范
标题总结发现而非描述图表("收入环比增长 15%" 而非 "收入柱状图")
坐标轴必须有轴标签和单位
数据标签KPI 图必须有,密集数据不需要
图例尽量放在图内或使用直接标注
脚注数据来源、截止时间、口径说明

5. 减少认知负荷

好图表 vs 坏图表对比

问题坏实践好实践
饼图类别太多10 个扇区密密麻麻换成排序条形图
3D 效果3D 柱状图/饼图2D 即可
双 Y 轴两条线 Y 轴范围不同用分面或灰色参考线
Y 轴截断柱状图 Y 轴从 90 开始从 0 开始或明确标注
彩虹配色每根柱不同颜色同色系,仅高亮重点
缺少上下文只有一周的数据加入同比/目标参考线

常见面试问题

Q1: 怎么判断一张图是不是好图?

答案:问自己三个问题:

  1. 5 秒钟能看出结论吗?(不能 → 太复杂)
  2. 每个视觉元素都在传达数据吗?(装饰太多 → chartjunk)
  3. 没有误导吗?(Y 轴截断、面积扭曲 → 误导)

Q2: 图表标题应该怎么写?

答案

  • ❌ 描述性标题:"各渠道用户数柱状图"
  • ✅ 洞察性标题:"搜索渠道贡献了 40% 的新用户"
  • 让读者不用看图就能知道核心发现

Q3: viridis 调色板为什么推荐?

答案

  • 感知均匀:颜色变化速度一致,不会某段看起来变化更大
  • 色盲友好:红绿色盲者也能区分
  • 灰度友好:黑白打印后仍能区分深浅
  • 适用于热力图、地理图等连续数据场景

相关链接