ggplot2(6) 标度、坐标轴和图例
6.1 简介
标度控制着数据到图形属性的映射。标度将我们的数据转化为视觉上可以感知的东西:例如大小、颜色、位置和形状。标度也为我们提供了读图时所使用的工具:坐标轴和图例。
执行标度的过程分为三步:变换、训练和映射。
标度可以粗略地分为四类:位置标度、颜色标度、手动离散型标度以及同一型标度。
6.2 标度的工作原理
标度的定义域即数据空间,值域即图形属性空间。当输入变量是离散型时,标度的定义域是某些值组成的集合,它的值域是输入值对应的图形属性值组成的一个向量;当输入变量是连续型时,标度的定义域是一个实值区间,它的值域是穿过某种更复杂的空间的一条一维路径,例如,从一种颜色到另一种颜色进行线性插值得到的一组渐变颜色。
- 变换:对连续型数据进行适当的变换往往是有益的,例如取对数或者开根号。
- 训练:通过学习得到标度的定义域,在一个仅有一个图层且仅呈现原始数据的图形中,这个学习过程包括确定某个连续型变量的最大值和最小值,或者是列出某个类别型变量的所有水平。
- 映射:执行映射数据到图形的函数。
6.3 用法
每一种图形属性都拥有一个默认的标度,此标度将在我们每次使用这个图形属性时被自动地添加到图形中。
图形属性 | 离散型 | 连续型 |
颜色(colour)和填充色(fill) | brewer | gradient |
gery | gradient2 | |
hue | gradientn | |
identity | ||
manual | ||
位置(position)(x, y) | discrete | continuous |
date | ||
形状(shape) | shape | |
identity | ||
manual | ||
线条类型(line type) | linetype | |
identify | ||
manual | ||
大小(size) | identity | size |
manual |
如果要添加一个不同的标度或者修改默认标度的某些特征,我们必须构造一个新的标度,然后使用+将其添加到图形上。所有的标度构建器都有一套通用的命名方案。它们以scale_开头,接下来是图形属性的名称(例如,colour_、shape_或x_),最后以标度的名称结尾(例如,gradient、hue或manual)。举例来说,离散型数据的颜色图形属性的默认标度名为scale_colour_hue(),填充色的Brewer配色标度名为scale_fill_brewer()。
p <- qplot(sleep_total, sleep_cycle, data = msleep, colour = vore) p # 显式添加默认标度 p + scale_colour_hue() # 修改默认标度的参数, 这里改变了图例的外观 p + scale_colour_hue("What does\nit eat?", breaks = c("herbi", "carni", "omni", NA), labels = c("plants", "meat", "both", "don’t know")) # 使用一种不同的标度 p + scale_colour_brewer(palette = "Set1")
调整标度默认参数的示例:(左上图)使用默认标度的图形。(右上图)手动添加默认标度,并未改变图形外观。(左下图)调整标度的参数以实现对图例的调整。(右下图)使用一种不同的颜色标度:ColorBrewer配色方案中的Set1。
6.4 标度详解
- 位置标度:用于将连续型、离散型和日期-时间型变量映射到绘图区域,以及构造对应的坐标轴;
- 颜色标度:用于将连续型和离散型变量映射到颜色;
- 手动离散型标度:用于将离散型变量映射到我们选择的符号大小、线条类型、形状或颜色,以及创建对应的图例;
- 同一型标度:用于直接将变量值绘制为图形属性,而不去映射它们。比如假设我们想要将变量映射为符号的颜色,而此变量本身就是一个由颜色值组成的向量,那么我们就无需再将其映射为其他的颜色,直接渲染这些值本身即可。
6.4.1 通用参数
以下参数对所有标度通用。
- name:设置坐标轴或图例上出现的标签。可以指定字符串(使用\n换行)或数学表达式(语法在??plotmath中)。由于经常需要微调这些标签,所以使用三个辅助函数xlab()、ylab()、labs()可以使我们减少部分输入。
p <- qplot(cty, hwy, data = mpg, colour = displ) p p + scale_x_continuous("City mpg") p + xlab("City mpg") p + ylab("Highway mpg") p + labs(x = "City mpg", y = "Highway", colour = "Displacement") p + xlab(expression(frac(miles, gallon)))
- limits:固定标度的定义域。连续型标度接受一个长度为2的数值型向量;离散型标度接受一个字符型向量。一旦设定了limits,数据将不再进行任何训练。限制定义域可以帮助我们移除不想在图形上展示的数据,或者保证要进行比较的多个图形中的绘制范围一致。
任何不在此标度定义域内的值均将被丢弃,丢弃过程发生在统计量的计算之前。
- breaks和labels:breaks控制着显示在坐标轴或图例上的值,即坐标轴上应该显示哪些刻度线的值,或者一个连续型标度在一个图例中将如何分段。labels指定了应在断点处显示的标签。若设置了labels,则必须同时指定breaks,只有这样,这两个参数才能被正确匹配。
- formatter:如果未指定任何标签,则将在每个断点处自动调用格式刷来生成标签。对于连续型标度,可用的标签刷为:comma、percent、dollar和scientific;对于离散型标度,则为abbreviate。
6.4.2 位置标度
- xlim(10, 20):一个从10到20的连续型标度;
- ylim(20, 10):一个从20到10的反转后连续型标度。
- xlim("a", "b", "c"):一个离散型标度;
- xlim(as.Data(c("2008-05-01", "2008-08-01"))):一个日期型标度。
在ggplot2中,为了保持与其他标度的一致性,任何在limits以外的数据都不会被绘制,也不会被包括在统计变换的过程中。这意味着,通过设置limits所得的结果与在视觉上放大一块绘图区域所得的结果是不同的。要实现后者,需要使用coord_cartesian()函数的参数xlim和ylim,这种方式单纯地对图形进行了视觉上的放大,而不影响底层函数的数据。
默认情况下,位置标度的limits会稍微超出数据的范围,这样就保证了数据与坐标轴不会发生重叠,我们可以使用参数expand来控制溢出量,此参数是长度为2的数值型向量,第一个参数给出的是乘式的溢出量,第二个参数给出的是加式的溢出量。使用expand = c(0, 0)来去掉任何多余的空间。
连续型
每个连续型标度均可接受一个trans参数,允许指定若干种线性或非线性变换。
scale_x_log10()与scale_x_continuous(trans = "log10")等价。
qplot(log10(carat), log10(price), data = diamonds) qplot(carat, price, data = diamonds) + scale_x_log10() + scale_y_log10()
直接绘制log10(x)和scale_x_log10()在绘图区域生成完全相同的结果,但坐标轴和刻度标签却是不同的。
日期和时间
对于日期坐标轴,有三个参数可以用于控制其外观和刻度的位置:major、minor和format。
- 参数major和minor用以按照时间的单位,及年(year)、月(month)、周(week)、日(day)、时(hour)、分(minute)、秒(second)来指定主要和次要断点的位置。并且允许以这些单位的倍数出现,例如,major = "2 weeks" 在每隔两周的位置放置一个主刻度。
- 参数format指定了刻度标签的格式。如下表所示。
编码 | 含义 |
%S | 秒(00-59) |
%M | 分钟(00-59) |
%l | 小时,12小时制(1-12) |
%I | 小时,12小时制(01-12) |
%H | 小时,24小时制(00-23) |
%a | 缩写的周几(Mon-Sun) |
%A | 全称的周几(Monday-Sunday) |
%e | 某月中的某天(1-31) |
%d | 某月中的某天(01-31) |
%m | 以数值表示的月份(01-12) |
%b | 缩写的月份(Jan-Dec) |
%B | 全称的月份(January-December) |
%y | 不含世纪的年份(00-99) |
%Y | 含世纪的年份(0000-9999) |
library(scales) p <- qplot(date, psavert, data = economics, geom = "line") + ylab("Personal savings rate") p p + scale_x_date(limits = as.Date(c("2004-01-01", "2005-01-01")), labels = date_format("%Y-%m-%d"))
6.4.3 颜色标度
连续型
- scale_colour_gradient()和scale_fill_gradient():双色梯度,顺序为从低到高,low和high用以控制此梯度两端的颜色。
- scale_colour_gradient2()和scale_fill_gradient2():三色梯度,low、high和midpoint。
- scale_colour_gradientn()和scale_fill_gradientn():自定义的n色标度。
此标度需要赋给参数colours一个颜色向量。不加其他参数的话,这些颜色将依照数据的范围均匀地分布。如果需要让这些值不均匀地分布,则可以使用参数values。如果rescale取值为TRUE(默认),则values应在0~1之间取值,如果rescale的取值为FALSE,则values应在数据范围内取值。
f2d <- with(faithful, MASS::kde2d(eruptions, waiting, h = c(1, 10), n = 50)) str(f2d) df <- with(f2d, cbind(expand.grid(x, y), as.vector(z))) names(df) <- c("eruptions", "waiting", "density") str(df) erupt <- ggplot(df, aes(waiting, eruptions, fill = density)) + geom_tile() + scale_x_continuous(expand = c(0, 0)) + scale_y_continuous(expand = c(0, 0)) erupt + scale_fill_gradient(limits = c(0, 0.04), low = "white", high = "black") erupt + scale_fill_gradient2(limits = c(-0.04, 0.04), midpoint = mean(df$density)) erupt + scale_fill_gradientn(colours = topo.colors(10)) erupt + scale_fill_gradientn(colours = terrain.colors(10)) erupt + scale_fill_gradientn(colours = heat.colors(10)) #自定义 erupt + scale_fill_gradientn(values = c(0,0.2,0.4,0.6,0.8,1), colors = c("red", "yellow", "green", "blue", "purple"))
kde2d {MASS}:Two-Dimensional Kernel Density Estimation;
expand.grid {base}:Create a Data Frame from All Combinations of Factor Variables。
离散型
离散型数据有两种颜色标度,一种可以自动选择颜色,另一种从手工甄选的颜色集中选择颜色。
RColorBrewer::display.brewer.all()
默认的配色方案即scale_colour_hue()可以通过沿着hcl色轮选取均匀分布的色相来生成颜色。缺点是:颜色多于8种时区分困难;所有的颜色都拥有相同的明度和彩度,所以在进行黑白打印时几乎成为相同的灰影。
使用ColorBrewer配色:对点一般使用"set1"和"Dark2",对面积则是"Set2"、"paster1"、"Pastel2"和"Accent"。这是因为更明亮的颜色对点效果良好,但对于条形来说过于刺眼。淡色对条形效果良好,但会让点看不清楚。
point <- qplot(brainwt, bodywt, data = msleep, log = "xy", colour = vore) area <- qplot(log10(brainwt), data = msleep, fill = vore, binwidth = 1) point + scale_colour_brewer(palette = "Set1") point + scale_colour_brewer(palette = "Set2") point + scale_colour_brewer(palette = "Pastel1") area + scale_fill_brewer(palette = "Set1") area + scale_fill_brewer(palette = "Set2") area + scale_fill_brewer(palette = "Pastel1")
6.4.4 手动离散型标度
离散型标度scale_linetype()、scale_size_discrete()和scale_shape()基本上没有选项,这些标度仅仅是按照一定的顺序将因子的水平映射到一系列的取值中。如果需要定值这些标度,可以使用scale_linetype_manual()、scale_colour_manual()和scale_shape_manual()。如果values向量中的元素师有名称的,则它将自动匹配输入和输出可用的图形属性值,否则将按照离散型变量中水平的先后次序进行匹配。
plot <- qplot(brainwt, bodywt, data = msleep, log = "xy") plot + aes(colour = vore) + scale_colour_manual(values = c("red", "orange", "yellow", "green", "blue")) colours <- c(carni = "red", `NA` = "orange", insecti = "yellow", herbi = "green", omni = "blue") plot + aes(colour = vore) + scale_colour_manual(values = colours) plot + aes(shape = vore) + scale_shape_manual(values = c(1, 2, 6, 0, 23))
使用colours()得到R中支持的详细的颜色列表。
> head(colours(),10) [1] "white" "aliceblue" "antiquewhite" "antiquewhite1" [5] "antiquewhite2" "antiquewhite3" "antiquewhite4" "aquamarine" [9] "aquamarine1" "aquamarine2"
多变量绘图!!
ggplot(huron, aes(year)) + geom_line(aes(y = level - 5, colour = "below")) + geom_line(aes(y = level + 5, colour = "above")) + scale_colour_manual("Direction", values = c(below = "blue", above = "red"))