# 第 7 章 原则

“情况的确如此，我在这方面有直觉。偶尔也会出现一些较复杂的案子，那我就得忙碌一阵子，亲自去查访一番。要知道，我有许多特殊知识，可以用来解开这些谜团，而且能轻易地解决问题。那篇文章中讨论的推理的原则，让你很鄙视，但对我的实际工作却是无价之宝。敏锐的观察力是我的第二天性。我们俩第一次见面时；我说起你是从阿富汗来的，你那时似乎很惊讶哩。”

— 柯南·道尔《血字的研究》

## 7.1 数据至上

### 7.1.1 分清主次

R 基础图形系统中默认的点的样式是空心点，在很多情况下这并不是一个好的选择，因为空心点在图中看起来太不起眼，尤其是数据点较少的时候。我们延续 6.2.4 小节中的美剧演员收入数据，在这里讨论如何突出主要元素。图 7.1 是演员收入与电视剧评分的散点图，左图使用了默认的空心点，右图使用了实心点。这批数据的样本量只有 72，左图中的点所用的墨水可能和坐标轴等次要元素差不多，所以数据在图中也显得不够突出，而实心点则很明显占据了一幅图的视觉重心。

par(mfrow = c(1, 2))
data("tvearn", package = "MSG")
plot(pay/10^4 ~ rating, data = tvearn, ylab = "pay (10^4)") # 默认为空心点
plot(pay/10^4 ~ rating, data = tvearn, pch = 19, ylab = "pay (10^4)") # 改为实心点

par(mfrow = c(1, 2), mar = c(3.2, 3.6, .05, .05))
plot(log10(pay) ~ rating, data = tvearn, pch = 19)
plot(log10(pay) ~ rating, data = tvearn, pch = 20, ylab = "", col = "red")
with(tvearn, car::pointLabel(rating, log10(pay), labels = actor,
cex = .6, col = "#00000099", xpd = TRUE))

data("music", package = "MSG")
par(mar = c(0, 2, 0, 0))
# 标准化所有频率变量到 0-1 之间并计算曲目之间欧式距离
st.music <- apply(music[, -(1:2)], 2, function(x) {
(x - min(x)) / (max(x) - min(x))
})
fit <- cmdscale(dist(st.music))
plot(fit, type = "n", ann = FALSE, axes = FALSE)
text(fit[, 1], fit[, 2], rownames(music), cex = .7, xpd = TRUE)

### 7.1.2 符号明确可分

char_gen(c("O", "Q"), n = 320, nrow = 8) # 从 Q 中找 O
## QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
## QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
## QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
## QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
## QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
## QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
## QQQQQQQQQQQQQQQQQQQQQQQQQQQQOQQQQQQQQQQQ
## QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
char_gen(c("*", "Q"), n = 320, nrow = 8) # 从 Q 中找 *
## QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
## QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
## QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
## QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
## QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
## QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
## QQQQQQQQQQQQQQ*QQQQQQQQQQQQQQQQQQQQQQQQQ
## QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ

### 7.1.3 谨慎处理数据

Cleveland (1985) 中给了一个省略数据的例子，可以看作是 1986 年美国挑战者号航天飞机失事的原因之一，大意是航天局的工程师们在发射之前研究了 O 型环的故障与温度的关系，他们看的是一幅散点图，横轴为温度，纵轴为 O 型环发生故障的数量，从散点图中来看，温度与这个零件的故障数量并没有什么联系，然而最终挑战者号还是因为温度原因发射失败并解体爆炸。那么这幅散点图有什么问题呢？首先，它只画出了零件失效的情况，而省略了零件未失效的那些观测数据，退一步讲，他们的散点图中即使没有观察到零件失效与温度的关系，也不能代表温度与零件不失效没有关系，而事实是如果把零件未失效的数量和相应的温度加上去的话，我们就能观察到低温情况下 O 型环容易发生故障；其次，这幅散点图中的温度范围不够大，而发射当前的气温是 31 华氏度（零下 1 摄氏度），属于超低温，这样的情况也没有在以往数据中观察到，因此这个发射行动是非常鲁莽的。

set.seed(319)
x <- rnorm(100)
y <- rnorm(100)
par(mfrow = c(1, 2)) # 以下 cut_plot() 函数来自 MSG 包
cut_plot(x, y, c(-2.02, -0.9, -0.3, 1, 2, 2.5), col = "gray")
cut_plot(x, y, c(-2.02, 0, 0.25, 0.5, 2.8, 3), col = "gray")

7.4 展示了离散化数据的一种弊病：左右两幅图中的数据完全相同，只是两幅图中我们用了不同的分组区间去将变量 x 离散化为 5 组，竖着的虚线表示分组的端点，在每一组内我们计算 y 的均值并连线，左图中我们看到数据有下降趋势，右图则显示为上升趋势，而事实是 x 和 y 是独立的，毫无关系。这就像盲人摸象的故事 — 有人摸到了耳朵说它像扇子，有人摸到了尾巴说像绳子。

## 7.2 节约墨水

Cleveland 也有类似的观点，提倡用尽量简单的图形元素表达尽量多的数据信息；用更量化的指标来说，就是“数据/墨水比”要尽量高，意思是用少的墨水打印出多的数据。Cleveland 提出他的点图（4.11 小节）也有此考虑，因为点图中的图形元素占用的空间小，但和条形图一样能表达出数字的大小。

Tufte (2001) 中提到一个浪费墨水的极端例子，他本人的评论为“它可能是史上出版物中最糟糕的图形”（This may well be the worst graphic ever to find its way into print），这幅图由《美国教育》杂志发表，如图 7.5 所示。这幅看起来很炫目的图到底画了什么？其实只是 5 个数字，记录了 1972 到 1976 年中，25 岁及以上的美国大学生录取比例；该图的标题为“大学新生年龄结构”，而这个所谓的“结构”分两类，一类是 25 岁及以上的新生，另一类是 25 岁以下的，这两个比例相加为 100%，图下半边代表了 25 岁及以上的学生，这 5 个比例分别为 28.0%、29.2%、32.8%、33.6% 和 33.0%，这便是这幅三维立体图形要表达的全部，图的上半边是下半边的“倒影”。Michael Friendly 在他的数据可视化网站（http://www.datavis.ca/）中也给出了评价：

## 7.3 设计布局

layout(matrix(1:2, 2), heights = c(2, 1))
par(mar = c(4, 4, 0.1, 0.1))
plot(sunspots)
plot(sunspots, asp = .1)

R 基础图形系统中通常用 asp 参数设置纵横比，下面我们给一个经典例子来说明它的作用。图 7.6 是 1749 到 1984 年太阳黑子数量的时间序列图，数据为月度数据。我们都知道太阳黑子的数量有周期性，其周期大约为 11 年，这一点在图中可以很容易看出来（折线有规律地起伏）。图 7.6 上图使用的是默认纵横比设置，即纵横比随着图形大小自动调整，而下图中固定为 0.1，初看起来这两幅图没有什么不同，但下图揭示了一个重要的发现：太阳黑子数量上升时的速度比下降的速度更快，注意观察图中上升的折线比下降的折线更陡峭，而上图中则很难看出这个现象，因为折线斜率太大。关于图 7.6 我们要补充说明的是，下图并不是简单地把高度压缩了一下而已，即使图形的高度更高，图中的折线形状也不会变化，关于这一点读者可以自行验证。

Cleveland 对这个问题的建议是调整纵横比让所有的折线的倾斜角度平均值接近 $$45\,^{\circ}$$（banking to $$45\,^{\circ}$$），因为人眼对 $$45\,^{\circ}$$ 附近的角度感知最精确，而对太大或者太小的角度感知都很差，例如图 7.6 中为什么我们更难看出上图中的折线角度差异？

## 7.5 考虑心理

set.seed(320)
par(mar = c(1, 0, 1, 0), xpd = TRUE)
plot.new()
h <- runif(4)
v <- runif(4, 0, .4)
arrows(v[1:2], h[1:2], v[1:2] + .6, h[1:2], angle = 45, code = 3)
arrows(v[3:4], h[3:4], v[3:4] + .6, h[3:4], angle = 135, code = 3, col = 2)
• 红色为夸张色，所以红色区域可能看起来比实际大小更大
• 大区域中的填充颜色看起来比小区域更深一些
• 同一个角度在不同方向上放置可能会导致它看起来不一样，例如从水平线出发的角度和从 $$45\,^{\circ}$$ 角出发的同一个角看起来大小不同，这会影响饼图的解读

Cleveland (1985) 在一些心理学实验基础上将一系列视觉判断任务按照人眼感知精度从高到低排了以下顺序：

1. 位置
2. 长度
3. 斜率和角度
4. 面积
5. 体积
6. 颜色（顺序：色调、饱和度和亮度）

set.seed(320)
par(mfrow = c(1, 2))
x <- matrix(rnorm(200), ncol = 2)
plot(x,
pch = c(4, 19)[kmeans(x, centers = 2)\$cluster],
xlab = expression(x[1]), ylab = expression(x[2])
)
library(alphahull)
plot(ahull(x, alpha = 0.4), xlab = expression(x[1]), ylab = expression(x[2]))

## 7.6 统计原则

Koyama (2010) 给出了一个很好的例子来说明误差线图的弊端，这里我们也可以模拟类似的数据。图 7.9 展示了一幅误差线图（左）和它背后的真实数据（右）。如果只看误差线图，那么我们的印象可能是 A 组和 B 组的分布一样，因为它们的均值相同（条形图的高度代表均值），均值的标准误也相同（误差线的高度代表 2 倍的标准误），C 组和 D 组也一样。真实情况是 A、B、C、D 组背后的数据分布大不相同：A 组为均匀分布，样本量 20，B 组只有 2 个点，C 组由 1 个离群点和剩下聚成一团的 9 个点构成，D 组由两类点构成。对数据的压缩掩盖了这些完全不同的分布情况。

set.seed(321)
par(mfrow = c(1, 2), mar = c(4, 4, .5, .1))
y <- c(runif(20), c(.43, .54), c(.6, runif(9, .3, .4)),
c(runif(6, .5, .6) - .12, runif(4, .15, .22) + .12)) - .2
x <- factor(rep(LETTERS[1:4], c(20, 2, 10, 10)))
mid <- barplot(m <- tapply(y, x, mean), col = 1:4, ylim = c(0, .4))[, 1]
s <- 2 * tapply(y, x, sd) / sqrt(table(x))
arrows(mid, m - s, mid, m + s, code = 2, col = 1:4, angle = 90, length = .15)
stripchart(y ~ x, vertical = TRUE, method = "jitter", pch = 20)

## 7.7 思考与练习

1. 我们可以把 7.1.2 小节中的找 O 和找 * 的任务当作一个游戏请你的朋友来玩，若有可能，请记录下他 / 她完成这两个任务分别使用的时间以及相关背景信息（在不侵犯隐私的情况下）并发给作者；或者用 MSG 包中的 char_gen() 函数生成更多任务去玩。

2. Cleveland 提出了 4.11 小节介绍的 Cleveland 点图，它的优势之一是数据 / 墨水比相对较高，因为一个点占用的面积比一个矩形条要小得多，看起来这些点也表达了和条形图等量的信息。仔细观察 Cleveland 点图，你认为它是否“让数据突出出来”了？或者你认为点图读起来方便吗？

3. Lane and Sándor (2009) 是一篇相对较新的关于作图原则的论文，它总结了不少有用的原则，请阅读这篇论文并考虑其中的原则是否都有足够的说服力。例如作者建议通常情况下不要用背景颜色，而我们知道 ggplot2 系统的图形通常都带有灰色背景，它们是否有冲突？

4. Michael Friendly 的数据可视化网站是一个具有丰富图形资源的网站，尤其值得称道的是他对统计图形历史的资料总结，同时他也给了很多劣质图形的例子，比如某杂志封面上关于康奈尔大学的学费和排名折线图（http://www.datavis.ca/gallery/context.php），可以说是极具误导性，请仔细阅读这些案例，并寻找我们身边的杂志和媒体中有哪些糟糕的统计图形。

5. 压缩数据导致损失信息并不是统计图形特有的现象，我们身边经常能看到这种例子。比如我们看到一些重要的统计数据只公布均值的时候，甚至觉得不平，感觉就像“被（均值）代表”了一样。我们应该采取怎样的行动让人们拥有足够的保护原始数据的意识？

### 参考文献

———. 1985. The Elements of Graphing Data. Monterey, CA: Wadsworth.
Koyama, Tatsuki. 2010. Beware OF Dynamite. http://biostat.mc.vanderbilt.edu/twiki/pub/Main/TatsukiRcode/Poster3.pdf.
Lane, D. M., and A. Sándor. 2009. “Designing Better Graphs by Including Distributional Information and Integrating Words, Numbers, and Images.” Psychological Methods 14 (3): 239–57. https://doi.org/10.1037/a0016620.
Pateiro-Lopez, Beatriz, Alberto Rodriguez-Casal, and. 2022. Alphahull: Generalization of the Convex Hull of a Sample of Points in the Plane. https://CRAN.R-project.org/package=alphahull.
Robinson, Heman. 2003. “Usability of Scatter Plot Symbols.” Statistical Computing and Graphics Newsletter 14 (1). http://stat-computing.org/newsletter/issues/scgn-14-1.pdf.
———. 2001. The Visual Display of Quantitative Information. 2nd ed. Cheshire, CT, USA: Graphics Press.
———. 2010. “统计图形和模拟视角下的模型理论解析.” Master’s thesis, 中国人民大学. http://1t.click/ajnW.