11 色阶与图例
除了位置之外,最常用的属性是基于颜色的图形属性,在ggplot2中有许多方法将值映射到颜色。在我们具体了解之前,学习一点色彩理论是很有用的。颜色理论很复杂,因为眼睛和大脑的基础生物学很复杂,此处只介绍一些更重要的问题。更详细的内容可以在线访问http://tinyurl.com/clrdtls了解。
11.1 简单的色彩原理
在物理层面上,颜色是由不同波长的光混合产生的。要完全描述一种颜色,我们需要知道波长的完全混合后的效果。然而,人眼只有三种不同的颜色感受器,因此我们可以用三个数字来概括对任何颜色的感知。你可能对颜色空间的RGB编码很熟悉,它通过产生颜色所需的红、绿、蓝光的强度来定义颜色。这个空间的一个问题是它在感知上不是统一的:相隔一个单位的两种颜色可能看起来相似或非常不同,这取决于它们在颜色空间中的位置。这使得创建一个从连续变量到一组颜色的映射变得困难。我们将使用一种叫做HCL色彩空间做尝试,它有色调、色度和亮度三个组成部分:
- 色调范围从 0 到 360(角度),并给出具体的“颜色”(蓝色、红色、橙色等)。
- 色度是颜色的“纯度”,范围从 0(灰色)到随亮度变化的最大值。
- 亮度是颜色的亮度,范围从 0(黑色)到 1(白色)。
这三个维度具有不同的属性。色调围绕一个色轮排列,并认为是无序的:例如,绿色看起来并不比红色“大”,蓝色似乎不在绿色或红色“中间”。相比之下,色度和亮度都被认为是有序的:粉红色被认为介于红色和白色之间,而灰色被认为介于黑色和白色之间。
这三个组件的组合不会产生简单的几何形状。下图显示了HCL空间的 3d 形状。每个切片都是一个恒定的亮度(亮度),色调映射到角度,色度映射到半径。您可以看到每个切片的中心是灰色的,并且颜色越靠近边缘越浓。
需要注意的是,许多人(约10%的男性)没有正常的颜色受体,因此能够区分的颜色比平常少。简而言之,最好避免红绿对比,通过使用Visicheck(在线解决方案)模拟色盲的系统检查您的图。另一种替代方案是dichromat包,它提供模拟色盲的工具,以及一套已知对色盲很有效的配色方案。你也可以帮助色盲的人,就像你可以帮助黑白打印机的人一样:通过为其他图形属性(如尺寸、线条类型或形状)提供多于映射。
11.2 连续色阶
颜色渐变通常用于显示二维平面图形。本节中的图使用了faithful
数据集的二维密度估计的表面,记录了黄石公园在喷发之间和每次喷发期间的等待时间。我隐藏图例并设置expand
为 0,便于关注数据外观。请记住:虽然我使用erupt
绘图来说明使用填充属性的概念,但同样的想法也适用于色阶。在本节中,无论我何时引用scale_fill_*()
,都有一个相应的scale_colour_*()
用于颜色图形属性(或者scale_color_*()
)。
erupt <- ggplot(faithfuld, aes(waiting, eruptions, fill = density)) +
geom_raster() +
scale_x_continuous(NULL, expand = c(0, 0)) +
scale_y_continuous(NULL, expand = c(0, 0)) +
theme(legend.position = "none")
11.2.1特殊调色板
有多种方法可以指定连续的色阶。稍后我将讨论可用于构建自己的调色板的通用工具,但这通常是不必要的,因为有许多“hand picked”的调色板可用。例如,ggplot2 提供了两个scale函数,它们预定义了调色板,scale_fill_viridis_c()和scale_fill_distiller().。翠绿色(viridis scales)的设计是为了使其在颜色和黑白两种颜色上都具有感知上的统一,并使各种形式的色盲的人能够感知到。
erupt
erupt + scale_fill_viridis_c()
erupt + scale_fill_viridis_c(option = "magma")
ggplot2 内置的第二个连续色阶源自 ColorBrewer 色标:scale_fill_brewer()将这些颜色作为离散调色板提供,而scale_fill_distiller()和scale_fill_fermenter()是连续和分箱相关。
erupt + scale_fill_distiller()
erupt + scale_fill_distiller(palette = "RdPu")
erupt + scale_fill_distiller(palette = "YlOrBr")
还有许多其他软件包提供有用的调色板。例如,scico包提供了更多在感知上统一的,并且适合科学可视化的调色板:
erupt + scico::scale_fill_scico(palette = "bilbao") # the default
erupt + scico::scale_fill_scico(palette = "vik")
erupt + scico::scale_fill_scico(palette = "lajolla")
然而,由于 R 中有很多调色板包,一个特别有用的是paletteer包,它提供了一个通用接口:
erupt + paletteer::scale_fill_paletteer_c("viridis::plasma")
erupt + paletteer::scale_fill_paletteer_c("scico::tokyo")
erupt + paletteer::scale_fill_paletteer_c("gameofthrones::targaryen")
11.2.2 稳定的方法
连续填充的默认方法是scale_fill_continuous(),反方向默认为scale_fill_gradient()。因此,这三个命令使用梯度比例生成相同的图形:
erupt
erupt + scale_fill_continuous()
erupt + scale_fill_gradient()
渐变为创建您喜欢的任何配色方案提供了一种强大的方法。您需要做的就是指定两个或多个参考颜色,ggplot2 将在它们之间进行线性插值。为此,您可以使用三个函数:
- scale_fill_gradient()产生两色渐变
- scale_fill_gradient2()产生具有指定中点的三色渐变
- scale_fill_gradientn()产生 n 色渐变
下面说明了梯度渐变的使用。第一个图使用线性插值的比例,从low
灰色(十六进制代码:“#bebebe”
)到high
端棕色(“#a52a2a”
)。第二个图形具有相同的端点,但使用scale_fill_gradient2()
首先从灰色插值到白色(#ffffff
),然后从白色插值到棕色。注意,mid
参数指定了颜色在中间点,midpoint
是该数据使用这个颜色(默认是midpoint = 0
)的值,第三种方法是使用scale_fill_gradientn()
将一个向量的参考颜色作为它的参数,并构建一个刻度,在指定的值之间线性内插。默认情况下,colours
沿比例是相等间隔的,但如果您愿意,您可以指定一个values
对应于每个参考颜色。
erupt + scale_fill_gradient(low = "grey", high = "brown")
erupt + scale_fill_gradient2(low = "grey", mid = "white", high = "brown", midpoint = .02)
erupt + scale_fill_gradientn(colours = terrain.colors(7))
创建好的调色板需要小心。通常,对于两点渐变比例,您希望传达值按顺序排列的感知印象,因此您希望保持色调不变,并改变色度和亮度。Munsell 颜色系统对此很有用,因为它提供了一种基于色调、色度和亮度指定颜色的简单方法。munsell 包提供了对 Munsell 颜色的轻松访问,然后可用于指定渐变比例:
munsell::hue_slice("5P") + # generate a ggplot with hue_slice()
annotate( # add arrows for annotation
geom = "segment",
x = c(7, 7),
y = c(1, 10),
xend = c(7, 7),
yend = c(2, 9),
arrow = arrow(length = unit(2, "mm"))
)
#> Warning: Removed 31 rows containing missing values (geom_text).
# construct scale
erupt + scale_fill_gradient(
low = munsell::mnsl("5P 2/12"),
high = munsell::mnsl("5P 7/12")
)
左图中的标签在这个比例下有点难以阅读,所以我习惯于annotate()添加箭头突出显示用于构建右侧比例的列。有关 munsell 软件包的更多信息,请参阅https://github.com/cwickham/munsell/。
三点梯度量表的设计标准略有不同。通常,这种量表的目标是传达一种感知印象,即存在其他值与之不同的自然中点(通常为零值)。下面的左图显示了如何创建发散的“黄色/蓝色”比例。
最后,如果您有对您的数据有意义的颜色(例如,黑色车身颜色或标准地形颜色),或者您想使用由另一个包生成的调色板,您可能希望使用 n 点渐变。作为说明,下面的中间和右边的图使用了colorspace包。有关色彩空间包的更多信息,请参阅https://colorspace.r-forge.r-project.org/。
# munsell example
erupt + scale_fill_gradient2(
low = munsell::mnsl("5B 7/8"),
high = munsell::mnsl("5Y 7/8"),
mid = munsell::mnsl("N 7/0"),
midpoint = .02
)
# colorspace examples
erupt + scale_fill_gradientn(colours = colorspace::heat_hcl(7))
erupt + scale_fill_gradientn(colours = colorspace::diverge_hcl(7))
11.2.3 缺失值
所有连续色阶都有一个na.value
参数,用于控制缺失值的颜色(包括标度限制范围之外的值)。默认情况下为灰色,当您使用彩色比例尺时,它会脱颖而出。如果您使用黑白比例,您可能希望将其设置为其他内容以使其更明显。您可以设置na.value = NA
使缺失值不可见,或者选择一个特定颜色:
df <- data.frame(x = 1, y = 1:5, z = c(1, 3, 2, NA, 5))
base <- ggplot(df, aes(x, y)) +
geom_tile(aes(fill = z), size = 5) +
labs(x = NULL, y = NULL)
base
base + scale_fill_gradient(na.value = NA)
base + scale_fill_gradient(na.value = "yellow")
11.2.4 限制、中断和标签
您可以通过将它们设置为NULL
来完全抑制中断。对于轴,这将删除刻度线、网格线和标签;对于图例,这将删除键和标签。
toy <- data.frame(
const = 1,
up = 1:4,
txt = letters[1:4],
big = (1:4)*1000,
log = c(2, 5, 10, 2000)
)
leg <- ggplot(toy, aes(up, up, fill = big)) +
geom_tile() +
labs(x = NULL, y = NULL)
leg + scale_fill_continuous(breaks = NULL)