R 数据可视化 —— ggplot scale设置
标度(scale)控制着数据映射到图形属性的具体细节,用于将数据转化为我们在视觉上能够感知的东西。如颜色、大小、位置、形状和透明度等。每个标度都有一个对应的函数,用于将数据空间的值(即函数的定义域)映射到图形属性空间(即函数的值域)。通过使用这些函数,就能够将我们的数据与图形属性连接起来。图形中的每种属性都有一个默认的标度函数。在前一节的例子中,我们并没有显示使用这些标度函数,因为在默认情况下,g
前言
标度(scale
)控制着数据映射到图形属性的具体细节,用于将数据转化为我们在视觉上能够感知的东西。如颜色、大小、位置、形状和透明度等。
每个标度都有一个对应的函数,用于将数据空间的值(即函数的定义域)映射到图形属性空间(即函数的值域)。
通过使用这些函数,就能够将我们的数据与图形属性连接起来。
图形中的每种属性都有一个默认的标度函数。在前一节的例子中,我们并没有显示使用这些标度函数,因为在默认情况下,ggplot2
会自动添加标度,而无需手动设置
标度详情
标度函数大致可以分为四类:
- 位置标度:用于坐标轴的控制
- 颜色标度:将数据变量映射到颜色
- 自定义标度(
manual
):手动自定义数据到图形属性的映射关系 - 非映射标度(
identity
):直接将变量值作为图形属性值使用,不做映射。例如,某些变量值本身代表的值颜色值(如red
、blue
等),不需要再进行转换了。
各种标度函数如下
这些函数,有几个共有的参数:
-
name
:设置坐标轴和图例上的标签,可以是字符串(支持\n
换行)或数学表达值。但一般会使用labs()
、xlab()
或ylab()
设置 -
limits
:限制定义域的范围,不在该范围的数据将会被删除 -
breaks
:用于控制在坐标轴或图例上显示的值,即坐标轴的刻度,如果是连续型数据,则会对数据进行分箱。 -
labels
:用于设置断点处的标签,要设置labels
必须同时设置breaks
。
例如
p1 <- ggplot(mtcars) +
geom_bar(aes(mpg)) +
scale_x_binned(name = expression(1+exp(2)))
p2 <- ggplot(mtcars) +
geom_bar(aes(mpg)) +
scale_x_binned() +
labs(title = "This is example", tag = "A", x = expression(1+exp(2)))
p3 <- ggplot(mtcars) +
geom_bar(aes(mpg)) +
scale_x_binned(name = expression(1+exp(2)), limits = c(10, 20),
)
p4 <- ggplot(mtcars) +
geom_bar(aes(mpg)) +
scale_x_binned(name = expression(1+exp(2)), limits = c(10, 20),
breaks = seq(10, 20, 2), labels = c("A", 'B', 'C', 'D', 'E', 'F'),
)
plot_grid(p1, p2, p3, p4, nrow = 2, ncol = 2)
在上面的例子中,我们借用 cowplot
的 plot_grid
函数来将多张图片绘制在一起
标度函数
1. 设置图表信息
labs()
函数可以设置图表的一些信息,如标题(title
)、子标题(subtitle
),或使用 caption
来提供数据来源信息,使用 tag
来区分多个图表
labs(
...,
title = waiver(),
subtitle = waiver(),
caption = waiver(),
tag = waiver()
)
xlab(label)
ylab(label)
ggtitle(label, subtitle = waiver())
示例
p <- ggplot(mtcars, aes(mpg, wt, colour = cyl)) + geom_point()
p2 <- p + labs(colour = "Cylinders")
p3 <- p + labs(x = "New x label")
p4 <- p + labs(title = "New plot title")
p5 <- p + labs(title = "New plot title", subtitle = "A subtitle")
p6 <- p + labs(caption = "(based on data from ...)")
p7 <- p + labs(title = "title", tag = "A")
p8 <- p + labs(title = "title") + labs(title = NULL)
plot_grid(p, p2, p3, p4, p5, p6, p7, p8, nrow = 4, ncol = 2,
labels = c("A", 'B', 'C', 'D', 'E', 'F', 'G', 'H'))
在上面的例子中,第七张图的 tag
设置为 A
与 plot_grid
设置的 G
重合了。
而 xlab()
、ylab()
和 ggtitle()
是 labs()
的特殊化,专门用于设置 x
、y
轴的标签和标题
2. 设置范围
我们可以使用下面三个函数来设置数据的范围,这些函数是 limits
参数的快捷方式。
lims(...)
xlim(...)
ylim(...)
在默认的情况下,超出范围的数据都会被设置为 NA
值,这意味着超出范围的数据将会被删除
示例
xlim()
和 ylim()
函数接受两个数值,用于指定最小(左侧)或最大(右侧)的值。
如果更大的值在前面,轴的数据将会反转,你也可以将一个值设置为 NA
,让 ggplot2
来推断数值范围。
p1 <- ggplot(mtcars, aes(mpg, wt)) +
geom_point()
p2 <- ggplot(mtcars, aes(mpg, wt)) +
geom_point() +
xlim(15, 20)
p3 <- ggplot(mtcars, aes(mpg, wt)) +
geom_point() +
xlim(20, 15)
p4 <- ggplot(mtcars, aes(mpg, wt)) +
geom_point() +
xlim(NA, 20)
plot_grid(p1, p2, p3, p4,
labels = c('A', 'B', 'C', 'D')
)
对于 lims()
函数,接受一个 name-value
对。name
必须是图形属性,而值必须是长度为二的数值、字符串、因子或时间日期。
我们可以使用 lims
在不同的图片中设置同样的配色方案,如
small <- subset(mtcars, cyl == 4)
big <- subset(mtcars, cyl > 4)
p1 <- ggplot(small, aes(mpg, wt, colour = factor(cyl))) +
geom_point() +
lims(colour = c("4", "6", "8"))
p2 <- ggplot(big, aes(mpg, wt, colour = factor(cyl))) +
geom_point() +
lims(colour = c("4", "6", "8"))
plot_grid(p1, p2)
对于下面这个例子
last_month <- Sys.Date() - 0:59
df <- data.frame(
date = last_month,
price = c(rnorm(30, mean = 15), runif(30) + 0.2 * (1:30))
)
p <- ggplot(df, aes(date, price)) +
geom_line() +
stat_smooth()
我们可以有两种方式来设置轴的范围
p + lims(x= c(Sys.Date() - 30, NA), y = c(10, 20))
p + coord_cartesian(xlim =c(Sys.Date() - 30, NA), ylim = c(10, 20))
3. 设置值范围
除了设置坐标轴的范围,我们也可以设置图形中必须包含某个或某些值。
可以使用 expand_limits()
函数,该函数接受一个命名列表,名称必须为图形属性
示例
对于下面这张散点图
p <- ggplot(mtcars, aes(mpg, wt)) + geom_point()
> mtcars %>% distinct(mpg) %>% summarise(min=min(.), max=max(.))
min max
1 10.4 33.9
> mtcars %>% distinct(wt) %>% summarise(min=min(.), max=max(.))
min max
1 1.513 5.424
从上面的结果中,我们可以计算出:X
轴(mpg
)和 Y
轴(wt
)的数据范围
下面,让我们用 expand_limits
来调整数据范围
p1 <- p + expand_limits(x = 0)
p2 <- p + expand_limits(y = c(1, 9))
p3 <- p + expand_limits(x = 0, y = 0)
plot_grid(p1, p2, p3, labels = c('A', 'B', 'C'), nrow = 1)
在图 A
中,我们设置 X
轴数据要包含 0
,尽管并没有对应的值,但是 X
坐标轴还是会从 0
开始。
类似的,图 B
设置了 Y
轴需要包含 1
和 9
,超过了数据的范围,相当于扩大了 Y
轴的范围
我们还可以对颜色进行设置
p1 <- ggplot(mtcars, aes(mpg, wt)) +
geom_point(aes(colour = cyl)) +
expand_limits(colour = seq(2, 10, by = 2))
p2 <- ggplot(mtcars, aes(mpg, wt)) +
geom_point(aes(colour = factor(cyl))) +
expand_limits(colour = factor(seq(2, 10, by = 2)))
plot_grid(p1, p2, labels = c('A', 'B'))
A
图设置了渐变色,B
图是离散配色。
> mtcars %>% distinct(cyl)
cyl
Mazda RX4 6
Datsun 710 4
Hornet Sportabout 8
我们可以看到,其实颜色的值只有三个 4
、6
、8
,但是我们设置了 5
个不同的颜色层级。
从 B
图可以明显看出,2
和 10
的颜色并没有显示,因为不存在相应的数据
4. 设置间隔
可以使用 expansion()
函数设置数据与轴之间的间隔,该函数主要搭配 scale_(x|y)_continuous
与 scale_(x|y)_discrete
使用。
# 推荐使用
expansion(mult = 0, add = 0)
# 已被弃用
expand_scale(mult = 0, add = 0)
该函数包含两个参数:
mult
: 百分比间距,接受一个向量,如果向量长度为1
,则上下间距的间隔是一样的,如果长度为2
,则mult[1]
为下间距,mult[2]
为上间距add
: 常数值单位间距,类似mult
示例
p1 <- ggplot(mtcars) +
geom_bar(aes(x = factor(cyl)))
p2 <- ggplot(mtcars) +
geom_bar(aes(x = factor(cyl))) +
scale_y_continuous(expand = expansion(mult = c(0, .1)))
p3 <- ggplot(subset(diamonds, carat > 2), aes(cut, clarity)) +
geom_jitter() +
scale_x_discrete(expand = expansion(add = 2))
p4 <- ggplot(subset(diamonds, carat > 2), aes(cut, price)) +
geom_jitter() +
scale_x_discrete(expand = expansion(add = .6)) +
scale_y_continuous(expand = expansion(mult = .05))
plot_grid(p1, p2, p3, p4, labels = LETTERS[1:4],
nrow = 2)
其中,D
图所设置的间距是默认值
5. 设置透明度
alpha
透明度并不是非常有用,但它可以方便地从视觉上降低不太重要的观察结果的权重
设置透明度的函数包括:
scale_alpha(..., range = c(0.1, 1))
scale_alpha_continuous(..., range = c(0.1, 1))
scale_alpha_binned(..., range = c(0.1, 1))
scale_alpha_discrete(...)
scale_alpha_ordinal(..., range = c(0.1, 1))
其中 scale_alpha
是 scale_alpha_continuous
的别名,因为这个函数是最常用的。
其中 range
参数的值为透明度的范围,必须在 0-1
之间。
其他参数分别被 continuous_scale()
, binned_scale
, 和 discrete_scale()
解析
示例
首先在 aes
中设置透明度,如
p <- ggplot(mpg, aes(displ, hwy)) +
geom_point(aes(alpha = year))
然后使用标度函数来修改透明度范围
p1 <- p + scale_alpha("cylinders")
p2 <- p + scale_alpha(range = c(0.4, 0.8))
plot_grid(p1, p2, labels = LETTERS[1:2],
nrow = 1)
在图 A
中,我们传递了一个字符串,相当于设置了 name
参数的值,更改了图例的名称
自定义透明度
p <- ggplot(mpg, aes(displ, hwy)) +
geom_point(aes(alpha = factor(year)))
p + scale_alpha_manual(values = c(0.1, 0.2))
6. 设置线条类型
线条的类型可以使用 0-6
之间的整数来指定,分别代表
0 = blank 1 = solid
2 = dashed 3 = dotted
4 = dotdash 5 = longdash
6 = twodash
绘制所有的线条类型
df_lines <- tibble(
linetype = factor(0:6)
)
ggplot(df_lines) +
geom_hline(aes(linetype = linetype, yintercept = 0), size = 2) +
scale_linetype_discrete() +
facet_grid(linetype ~ .) +
theme_void(20)
线条类型不支持连续型数据,因为无法将连续型数据映射到线型。但是可以使用 scale_linetype_binned()
,由于线型没有固定的顺序,也不推荐这样使用
示例
对于数据
> economics_long
# A tibble: 2,870 x 4
date variable value value01
<date> <chr> <dbl> <dbl>
1 1967-07-01 pce 507. 0
2 1967-08-01 pce 510. 0.000265
3 1967-09-01 pce 516. 0.000762
4 1967-10-01 pce 512. 0.000471
5 1967-11-01 pce 517. 0.000916
6 1967-12-01 pce 525. 0.00157
7 1968-01-01 pce 531. 0.00207
8 1968-02-01 pce 534. 0.00230
9 1968-03-01 pce 544. 0.00322
10 1968-04-01 pce 544 0.00319
# … with 2,860 more rows
我们根据 variable
变量进行分组,绘制折线图
base <- ggplot(economics_long, aes(date, value01))
base + geom_line(aes(group = variable))
注意:我们是通过设置 group = variable
来设置分组的,但是组与组之间没有区分度。
为图片添加线型和颜色
base + geom_line(aes(linetype = variable, colour=variable))
这样,每组之间的趋势就很明显了。
自定义线条映射
df <- economics_long %>% filter(variable %in% c("pop", "pce", "uempmed"))
lt <- c("pop"=1, "pce"=3, "uempmed"=5)
ggplot(df, mapping = aes(date, value01)) +
geom_line(aes(linetype = variable, colour=variable)) +
scale_linetype_manual(values = lt)
7. 设置形状
scale_shape()
函数可以将离散变量映射为 6
个不同的形状。
如果你有超过 6
个类别,你将会得到一个警告信息,并且第 7
个或更后面的类别将不会在图片中显示
形状与线型一样,不支持连续型数据,也不推荐使用 scale_shape_binned
函数来设置
scale_shape(..., solid = TRUE)
scale_shape_binned(..., solid = TRUE)
其中 solid
参数控制形状是不是实心的
下面的代码展示了所有的形状
df_shapes <- data.frame(shape = 0:25)
ggplot(df_shapes, aes(0, 0, shape = shape)) +
geom_point(aes(shape = shape), size = 5, fill = 'red') +
scale_shape_identity() +
facet_wrap(~shape) +
theme_void()
取值范围为 0-25
,共 26
个整数值分别代表了相应的形状。
注意:红色的形状是可以设置填充色(fill
)的,其他形状只能设置轮廓颜色(colour
)。
示例
dsmall <- diamonds[sample(nrow(diamonds), 100), ]
d <- ggplot(dsmall, aes(carat, price)) + geom_point(aes(shape = cut))
p2 <- d + scale_shape(solid = FALSE)
p3 <- d + scale_shape(name = "Cut of diamond")
levels(dsmall$cut) <- c("Fair", "Good", "Very Good", "Premium", "Ideal")
p4 <- ggplot(dsmall, aes(price, carat)) + geom_point(aes(shape = cut))
plot_grid(d, p2, p3, p4, labels = LETTERS[1:4])
注意:在绘制图 D
时,会输出警告信息,提示不建议对排序的变量设置形状
自定义形状映射
shape_map <- c("Fair"=13, "Good"=20, "Very Good"=15, "Premium"=2, "Ideal"=11)
d + scale_shape(solid = FALSE) +
scale_shape_manual(values = shape_map)
8. 设置大小
一般只有点图和文本需要设置大小。而我们通常是将数据映射到点的面积,而不是映射到半径。
标度函数如下
scale_size(..., range = c(1, 6))
scale_radius(..., range = c(1, 6))
scale_size_binned(..., range = c(1, 6))
scale_size_area(..., max_size = 6)
scale_size_binned_area(..., max_size = 6)
如果需要将值为 0
的点映射为 0
,需要使用 scale_size_area
函数
示例
例如,下面这张散点图
p <- ggplot(mpg, aes(displ, hwy, size = hwy)) +
geom_point()
# 设置图例标题
p1 <- p + scale_size("Highway mpg")
# 设置点的大小范围
p2 <- p + scale_size(range = c(0, 10))
# 允许将 0 值映射为面积为 0 的点(不绘制)
p3 <- p + scale_size_area()
# 方便从看出图例中看出分箱
p4 <- p + scale_size_binned()
# This is most useful when size is a count
p5 <- ggplot(mpg, aes(class, cyl)) +
geom_count() +
scale_size_area()
# 将数据映射为半径,不推荐
p6 <- p + scale_radius()
plot_grid(p1, p2, p3, p4, p5, p6,
labels = LETTERS[1:6], nrow = 3)
自定义数据大小,我们根据 cyl
的值倒序设置点的大小
ggplot(mpg, aes(displ, hwy, size = factor(cyl))) +
geom_point() +
scale_size_manual(
name="cyl",
values = c(
"4" = 5,
"5" = 4,
"6" = 3,
"8" = 2
))
9. 位置
一幅图有两个位置标度,即指定水平位置的 X
轴和指定竖直位置的 Y
轴。
针对不同的数据类型,标度函数又可以分为连续型、离散型和日期标度。
9.1 连续型
连续型位置标度主要是 scale_x_continuous()
和 scale_y_continuous()
。用于将连续型数据映射到 X
和 Y
轴。
每个连续型标度函数都接受一个 trans
参数,用于对输入的数据进行变换后绘图。
内置的转换函数包括:
"asn", "atanh", "boxcox",
"date", "exp", "hms",
"identity", "log", "log10",
"log1p", "log2", "logit",
"modulus", "probability", "probit",
"pseudo_log", "reciprocal", "reverse",
"sqrt" "time"
一些常用的转换函数会有对应的简便写法,如
scale_x/y_log10()
scale_x/y_reverse()
scale_x/y_sqrt()
即 scale_x_log10()
和 scale_x_continuous(trans = "log10")
是等价的
当然,我们可以先对数据进行转换,然后再绘制图片。这样可以更好的自定义自己的转换方式
例如下面这个例子
p1 <- ggplot(diamonds, aes(log10(carat), log10(price))) +
geom_point()
p2 <- ggplot(diamonds, aes(carat, price)) +
geom_point() +
scale_x_log10() +
scale_y_log10()
plot_grid(p1, p2, labels = LETTERS[1:2])
可以看到,在绘图前后变换的数据主体是完全相同的,但是坐标轴的刻度却不一样。这将在后面的坐标系调整中进行说明
数据转换
p1 <- ggplot(mpg, aes(displ, hwy)) +
geom_point()
p2 <- p1 + scale_y_log10()
p3 <- p1 + scale_y_sqrt()
p4 <- p1 + scale_y_reverse()
plot_grid(p1, p2, p3, p4,
labels = LETTERS[1:4], ncol = 2)
也可以使用 scales
包定义的转换函数
p1 + scale_y_continuous(trans = scales::reciprocal_trans())
对数据进行分箱
p1 <- ggplot(mpg, aes(displ, hwy)) +
geom_point()
p2 <- p1 + scale_x_continuous(
breaks = c(2, 4, 6),
label = c("two", "four", "six")
)
plot_grid(p1, p2, labels = LETTERS[1:2])
使用 scales
包中的函数为轴标签设置格式
df <- data.frame(
x = rnorm(10) * 100000,
y = seq(0, 1, length.out = 10)
)
p2 <- ggplot(df, aes(x, y)) + geom_point()
p3 <- p2 + scale_y_continuous(labels = scales::percent)
p4 <- p2 + scale_y_continuous(labels = scales::dollar)
p5 <- p2 + scale_x_continuous(labels = scales::comma)
plot_grid(p2, p3, p4, p5,
labels = LETTERS[1:4], ncol = 2)
9.2 离散型
scale_x_discrete()
和 scale_y_discrete()
两个函数用于将离散型数据映射到坐标轴上。
d <- ggplot(subset(diamonds, carat > 1), aes(cut, clarity)) +
geom_jitter()
# 重置 X 轴的标签映射
p2 <- d + scale_x_discrete("Cut", labels = c("Fair" = "F","Good" = "G",
"Very Good" = "VG","Perfect" = "P","Ideal" = "I"))
p3 <- d + scale_x_discrete(limits = c("Fair","Ideal"))
p4 <- d + xlim("Fair","Ideal", "Good") + ylim("I1", "IF")
plot_grid(d, p2, p3, p4, labels = LETTERS[1:4], nrow = 2)
对标签进行重排
p1 <- ggplot(mpg, aes(manufacturer, cty)) + geom_point()
p2 <- ggplot(mpg, aes(reorder(manufacturer, cty), cty)) + geom_point()
p3 <- ggplot(mpg, aes(reorder(manufacturer, displ), cty)) + geom_point()
p4 <- ggplot(mpg, aes(reorder(manufacturer, displ), cty)) +
geom_point() +
scale_x_discrete(labels = abbreviate)
plot_grid(d, p2, p3, p4, labels = LETTERS[1:4], nrow = 2)
在 D
图中,我们使用 abbreviate
函数将 X
轴的标签设置为简写
9.3 日期和时间
虽然日期和时间也是连续型的,但是在标注坐标轴时还是有些不一样的。
共支持三种类型的时间日期,其中 scale_*_date
处理 Date
类型,scale_*_datetime
用于处理 POSIXct
类型的时间,scale_*_time
用于处理 hms
类型的时间
这些函数主要有三个特殊的参数
date_breaks
:一个字符串,用于设置时间间隔。如"2 weeks"
或"10 years"
。
如果同时指定 break
和 date_breaks
,则以 date_breaks
为准
date_labels
:一个字符串,为labels
提供格式化规范。
如果同时指定了 label
和 date_labels
,则以 date_labels
为准
常用的数据格式编码有:
更详细的格式介绍可以参考:
https://rdrr.io/r/base/strptime.html
date_minor_breaks
:一个字符串,给出次要标签之间的时间间距。如"2 weeks"
或"10 years"
。
如果同时指定了 minor_breaks
和 date_minor_breaks
,则以 date_minor_breaks
为准。
对于如下例子
last_month <- Sys.Date() - 0:29
df <- data.frame(
date = last_month,
price = runif(30)
)
base <- ggplot(df, aes(date, price)) +
geom_line()
设置格式
p1 <- p + scale_x_date(date_labels = "%b %d")
p2 <- p + scale_x_date(date_breaks = "1 week", date_labels = "%W")
p3 <- p + scale_x_date(date_minor_breaks = "1 day")
# 限制范围
p4 <- p + scale_x_date(limits = c(Sys.Date() - 7, NA))
plot_grid(p1, p2, p3, p4, labels = LETTERS[1:4], nrow = 2)
注意:在这里会有一个问题,就是英文月份无法显示。那该如何设置呢?
首先,尝试使用如下命令来设置
Sys.setlocale("LC_TIME", "English")
如果在运行该命令式报出如下错误
> Sys.setlocale("LC_TIME", "English") [1] "" Warning message: In Sys.setlocale("LC_TIME", "English") : 操作系统报告说无法执行将本地化设成"English"的请求
这个问题的原因可能是系统语言的问题,网上有人推荐说更改系统语言。但是这样改很麻烦,所以我尝试了如下代码
Sys.setlocale("LC_TIME", "C")
再次运行,已经解决了该问题了。不需要更改系统语言
10. 颜色
除了前面讲的位置标度之外,最常用的就是颜色属性的修改了。
配色也是一门艺术,像我这种没有艺术细胞的人就只能看着哪种配色方案漂亮就将就着用了🤣😂
10.1 ColorBrewer 配色
ColorBrewer
提供了 sequential
, diverging
和 qualitative
三种不同的配色类型,每种类型又有不同的配色方案。
有三个不同的标度函数来设置
# 针对离散型数据
scale_*_brewer()
# 针对连续型数据
scale_*_distiller()
# 针对分箱数据
scale_*_fermenter()
其中 *
代表 colour
(轮廓颜色) 和 fill
(填充色)。
palette
参数的值可以是下列字符串之一
Diverging
(双色渐变系)
BrBG, PiYG, PRGn, PuOr, RdBu, RdGy, RdYlBu, RdYlGn, Spectral
Qualitative
(多色系)
Accent, Dark2, Paired, Pastel1, Pastel2, Set1, Set2, Set3
Sequential
(单色系)
Blues, BuGn, BuPu, GnBu, Greens, Greys, Oranges, OrRd, PuBu, PuBuGn, PuRd, Purples, RdPu, Reds, YlGn, YlGnBu, YlOrBr, YlOrRd
示例
对于如下数据
dsamp <- diamonds[sample(nrow(diamonds), 1000), ]
我们可以为 colour
设置变量
(d <- ggplot(dsamp, aes(carat, price)) +
geom_point(aes(colour = clarity)))
但是我觉得这种配色不太好看,想换一种。我们进行如下尝试
p1 <- d + scale_colour_brewer()
p2 <- d + scale_colour_brewer(palette = "Greens")
p3 <- d + scale_colour_brewer(palette = "Set1")
p4 <- d + scale_colour_brewer(palette = "Spectral")
plot_grid(p1, p2, p3, p4, labels = LETTERS[1:4], nrow = 2)
en...
,这样来看,图 C
是比较好看的,图 D
看起来也行,单色系的就差了点喽。
连续型数据的设置方式也是类似的
d1 <- ggplot(dsamp, aes(carat, price)) +
geom_point(aes(colour = depth))
d2 <- d + scale_colour_distiller(palette = "Greens")
d3 <- d + scale_colour_distiller(palette = "Set1")
d4 <- d + scale_colour_distiller(palette = "Spectral")
plot_grid(d1, d2, d3, d4, labels = LETTERS[1:4], nrow = 2)
为分箱数据配色
ggplot(dsamp, aes(carat, price)) +
geom_point(aes(colour=depth)) +
scale_colour_fermenter(palette = "Spectral")
为每个分箱设置颜色相同的配色
ggplot(dsamp, aes(carat, price, colour=price)) +
geom_point() +
scale_x_binned() +
scale_colour_fermenter(palette = "Spectral")
获取更多的配色方案,可以访问 ColorBrewer
的网页:
配色好看,获取简单,推荐使用
还有一个网站
https://www.webdesignrankings.com/resources/lolcolors/
配色也还可以,只是都是 4
种颜色的。
10.2 渐变色
根据颜色梯度,可以将设置渐变色的函数分为三种:
-
scale_*_gradient
:双色渐变,使用low
和high
两个参数控制两端的颜色 -
scale_*_gradient2
:三色渐变,有low
、mid
和high
三个参数,low
和high
作用同上,mid
默认值为0
表示中点的颜色,可以使用midpoint
参数设置中点位置 -
scale_*_gradientn
:多色渐变,为colours
参数设置一个颜色向量,不加其他参数会选择范围内的均匀分布值,离散型颜色可以指定values
参数。
示例
对于如下数据
df <- data.frame(
x = runif(100),
y = runif(100),
z1 = rnorm(100),
z2 = abs(rnorm(100))
)
df_na <- data.frame(
value = seq(1, 20),
x = runif(20),
y = runif(20),
z1 = c(rep(NA, 10), rnorm(10))
)
其默认配色为浅蓝色到深蓝色的双色渐变
# 默认双色渐变
p1 <- ggplot(df, aes(x, y)) +
geom_point(aes(colour = z2))
# 调整双色渐变区间
p2 <- ggplot(df, aes(x, y)) +
geom_point(aes(colour = z2)) +
scale_colour_gradient(low = "white", high = "black")
# 三色渐变
p3 <- ggplot(df, aes(x, y)) +
geom_point(aes(colour = z1)) +
scale_colour_gradient2()
# 调整三色渐变区间
p4 <- ggplot(df, aes(x, y)) +
geom_point(aes(colour = z1)) +
scale_colour_gradient2(low = "green", high = "blue", midpoint = 1)
plot_grid(p1, p2, p3, p4, labels = LETTERS[1:4], nrow = 2)
自定义颜色范围,以及 NA
值的处理
# 自定义颜色范围,使用函数来生成 10 个连续的颜色
p5 <- ggplot(df, aes(x, y)) +
geom_point(aes(colour = z1)) +
scale_colour_gradientn(colours = topo.colors(10))
p6 <- ggplot(df, aes(x, y)) +
geom_point(aes(colour = z1)) +
scale_colour_gradientn(colours = rainbow(10))
# 去除 NA 值
p7 <- ggplot(df_na, aes(x = value, y)) +
geom_bar(aes(fill = z1), stat = "identity") +
scale_fill_gradient(low = "yellow", high = "red", na.value = NA)
p8 <- ggplot(df_na, aes(x, y)) +
geom_point(aes(colour = z1)) +
scale_colour_gradient(low = "yellow", high = "red", na.value = NA)
plot_grid(p5, p6, p7, p8, labels = LETTERS[1:4], nrow = 2)
10.3 灰色渐变
使用 start
和 end
控制灰度范围
示例
默认颜色
p <- ggplot(mtcars, aes(mpg, wt)) + geom_point(aes(colour = factor(cyl)))
p + scale_colour_grey()
更改设置
# 设置终端灰度
p1 <- p + scale_colour_grey(end = 0.5)
# 更改主题
p2 <- p + scale_colour_grey() + theme_bw()
# 缺失值
miss <- factor(sample(c(NA, 1:5), nrow(mtcars), replace = TRUE))
p3 <- ggplot(mtcars, aes(mpg, wt)) +
geom_point(aes(colour = miss)) +
scale_colour_grey()
# 更改缺失值的颜色
p4 <- ggplot(mtcars, aes(mpg, wt)) +
geom_point(aes(colour = miss)) +
scale_colour_grey(na.value = "green")
plot_grid(p1, p2, p3, p4, labels = LETTERS[1:4], nrow = 2)
10.4 分箱渐变色
分箱渐变色与渐变色类似,只是应用的数据不同。也有三个函数,对应于双色、三色以及多色渐变
scale_*_steps()
scale_*_steps2()
scale_*_stepsn()
用起来和渐变色很相似
df <- data.frame(
x = runif(100),
y = runif(100),
z1 = rnorm(100)
)
p1 <- ggplot(df, aes(x, y)) +
geom_point(aes(colour = z1))
p2 <- ggplot(df, aes(x, y)) +
geom_point(aes(colour = z1)) +
scale_colour_steps(low = "skyblue", high = "blue")
p3 <- ggplot(df, aes(x, y)) +
geom_point(aes(colour = z1)) +
scale_colour_steps2()
p4 <- ggplot(df, aes(x, y)) +
geom_point(aes(colour = z1)) +
scale_colour_stepsn(colours = terrain.colors(10))
plot_grid(p1, p2, p3, p4, labels = LETTERS[1:4], nrow = 2)
10.5 色轮颜色
这种设置方式主要用于将离散型数据均匀地映射到色轮上的颜色。
这种配色方案被称为 HLC
,包含三部分:
-
色相(
hue
):0-360
之间的值(代表角度),代表颜色。如红、黄、蓝等 -
亮度(
luminance
):表示颜色的明亮程度,0
表示黑色,100
表示白色 -
色度(
chroma
):颜色的纯度,色度为0
表示灰色,最大值根据色相和亮度的组合而变化
而标度函数
scale_*_hue(
...
h = c(0, 360) + 15,
c = 100,
l = 65,
)
有对应的参数 h
、c
、l
用于设置这些值。
示例
dsamp <- diamonds[sample(nrow(diamonds), 1000), ]
d <- ggplot(dsamp, aes(carat, price)) +
geom_point(aes(colour = clarity))
p1<- d + scale_colour_hue()
p2 <- d + scale_colour_hue("Clarity")
p3 <- d + scale_colour_hue(expression(clarity[beta]))
d + scale_colour_hue(l = 40, c = 30)
plot_grid(d, p1, p2, p3, labels = LETTERS[1:4], nrow = 2)
调整亮度和色相
p1 <- d + scale_colour_hue(l = 40, c = 30)
p2 <- d + scale_colour_hue(l = 70, c = 30)
p3 <- d + scale_colour_hue(l = 70, c = 150)
p4 <- d + scale_colour_hue(l = 80, c = 150)
plot_grid(p1, p2, p3, p4, labels = LETTERS[1:4], nrow = 2)
设置色相的范围
p1 <- d + scale_colour_hue(h = c(0, 90))
p2 <- d + scale_colour_hue(h = c(90, 180))
p3 <- d + scale_colour_hue(h = c(180, 270))
p4 <- d + scale_colour_hue(h = c(270, 360))
plot_grid(p1, p2, p3, p4, labels = LETTERS[1:4], nrow = 2)
设置透明度
d <- ggplot(dsamp, aes(carat, price, colour = clarity))
p2 <- d + geom_point(alpha = 0.9)
p3 <- d + geom_point(alpha = 0.5)
p4 <- d + geom_point(alpha = 0.2)
plot_grid(p2, p3, p4, labels = LETTERS[1:4], nrow = 3)
这个图设置透明度之后好看多了
给 NA
值设置特殊的颜色
miss <- factor(sample(c(NA, 1:5), nrow(mtcars), replace = TRUE))
p1 <- ggplot(mtcars, aes(mpg, wt)) + geom_point(aes(colour = miss))
p2 <- ggplot(mtcars, aes(mpg, wt)) +
geom_point(aes(colour = miss)) +
scale_colour_hue(na.value = "black")
plot_grid(p1, p2, labels = LETTERS[1:4], nrow = 2)
10.6 Viridis 配色
viridis
提供的颜色映射,让无论是在彩色还是黑白图片均能够很容易看出区别。
它还被设计能够让色盲观众也能看清
示例
对于如下数据
> dsamp <- diamonds[sample(nrow(diamonds), 1000), ]
> dsamp
# A tibble: 1,000 x 10
carat cut color clarity depth table price x y z
<dbl> <ord> <ord> <ord> <dbl> <dbl> <int> <dbl> <dbl> <dbl>
1 1.01 Very Good E SI1 62.1 56 5461 6.43 6.48 4.01
2 0.91 Premium F SI2 61.7 58 3609 6.22 6.29 3.86
3 1.26 Very Good H SI1 60.6 60 6546 6.97 7 4.23
4 1.31 Premium H VS2 61.4 59 7550 7.01 6.96 4.29
5 1.53 Very Good D SI1 59.2 57 11873 7.52 7.55 4.46
6 1.5 Ideal H SI2 62.4 58 8471 7.29 7.26 4.54
7 1.24 Premium F VS1 61.5 57 9333 6.97 6.86 4.25
8 1.14 Premium H SI1 59.3 59 5458 6.8 6.76 4.02
9 0.62 Very Good E SI2 63.4 56 1426 5.4 5.45 3.44
10 0.72 Premium G VS2 62.9 57 2795 5.73 5.65 3.58
# … with 990 more rows
默认的颜色设置方式会根据因子的顺序上色
ggplot(dsamp, aes(carat, price)) +
geom_point(aes(colour = clarity))
viridis_d
函数用于离散数据配色,可以使用 option
参数设置不同的调色板
# viridis_d 用于离散数据
txsamp <- subset(txhousing, city %in%
c("Houston", "Fort Worth", "San Antonio", "Dallas", "Austin"))
d <- ggplot(data = txsamp, aes(x = sales, y = median)) +
geom_point(aes(colour = city))
# 设置配色和标签
p1 <- d + scale_colour_viridis_d("City\nCenter")
# 选择调色板,使用 ?scales::viridis_pal 获取更多细节
p2 <- d + scale_colour_viridis_d(option = "plasma")
p3 <- d + scale_colour_viridis_d(option = "inferno")
plot_grid(d, p1, p2, p3, labels = LETTERS[1:4], nrow = 2)
设置填充色
# 设置填充色
p <- ggplot(txsamp, aes(x = median, fill = city)) +
geom_histogram(position = "dodge", binwidth = 15000)
p1 <- p + scale_fill_viridis_d()
# 反转颜色
p2 <- p + scale_fill_viridis_d(direction = -1)
plot_grid(p1, p2, labels = LETTERS[1:4], nrow = 2)
连续型数据及分箱数据颜色设置
# 连续型数据
v <- ggplot(faithfuld) +
geom_tile(aes(waiting, eruptions, fill = density))
p2 <- v + scale_fill_viridis_c()
p3 <- v + scale_fill_viridis_c(option = "plasma")
# 分箱数据
p4 <- v + scale_fill_viridis_b()
plot_grid(v, p2, p3, p4, labels = LETTERS[1:4], nrow = 2)
10.6 连续型和离散型
其实使用上面的函数已经够了,下面的操作也只是对上面的函数进行整合,功能都是一样的。
连续型
对于连续型数据的配色方案,其实我们上面也都涉及到。在这里我们要使用的是下面两个函数
scale_colour_continuous(
...,
type = getOption("ggplot2.continuous.colour", default = "gradient")
)
scale_fill_continuous(
...,
type = getOption("ggplot2.continuous.fill", default = "gradient")
)
这两个函数主要是通过获取 ggplot2.continuous.colour
和 ggplot2.continuous.fill
两个选项的值来设置颜色的,默认是渐变色
type
参数还可以设置为:
"viridis"
- 返回连续颜色向量的函数
示例
对于如下数据
> faithfuld
# A tibble: 5,625 x 3
eruptions waiting density
<dbl> <dbl> <dbl>
1 1.6 43 0.00322
2 1.65 43 0.00384
3 1.69 43 0.00444
4 1.74 43 0.00498
5 1.79 43 0.00542
6 1.84 43 0.00574
7 1.88 43 0.00592
8 1.93 43 0.00594
9 1.98 43 0.00581
10 2.03 43 0.00554
# … with 5,615 more rows
我们可以绘制一张热图
v <- ggplot(faithfuld, aes(waiting, eruptions, fill = density)) +
geom_tile()
更改颜色方案
p1 <- v + scale_fill_continuous(type = "gradient")
p2 <- v + scale_fill_continuous(type = "viridis")
p3 <- v + scale_fill_gradient()
p4 <- v + scale_fill_viridis_c()
plot_grid(p1, p2, p3, p4, labels = LETTERS[1:4], nrow = 2)
可以看到,A
与 C
,B
与 D
是一样的。
离散型
类似于连续型设置颜色的函数,离散型函数也是通过获取两个选项的值来设置颜色的
scale_colour_discrete(
...,
type = getOption("ggplot2.discrete.colour", getOption("ggplot2.discrete.fill"))
)
scale_fill_discrete(
...,
type = getOption("ggplot2.discrete.fill", getOption("ggplot2.discrete.colour"))
)
例如,我们要绘制如下图形
ggplot(mpg, aes(cty, colour = factor(class), fill = factor(class))) +
geom_density(alpha = 0.2)
默认是以 scale_fill_hue()
配色方案
使用 scale_*_discrete
来更改配色
okabe <- c("#E69F00", "#56B4E9", "#009E73", "#F0E442", "#0072B2", "#D55E00", "#CC79A7")
ggplot(mpg, aes(cty, colour = factor(class), fill = factor(class))) +
geom_density(alpha = 0.2) +
scale_color_discrete(type = okabe) +
scale_fill_discrete(type = okabe)
也可以通过设置 ggplot2.discrete.colour
或 ggplot2.discrete.fill
的值来更改配色
withr::with_options(
list(ggplot2.discrete.fill = okabe),
print(plot_cty(class))
)
还可以根据颜色变量的取值数目,设置默认的配色
discrete_palettes <- list(
c("skyblue", "orange"),
RColorBrewer::brewer.pal(3, "Set2"),
RColorBrewer::brewer.pal(6, "Accent")
)
p1 <- plot_cty(year) + scale_fill_discrete(type = discrete_palettes)
p2 <- plot_cty(drv) + scale_fill_discrete(type = discrete_palettes)
p3 <- plot_cty(fl) + scale_fill_discrete(type = discrete_palettes)
# 也可以传递返回离散颜色的函数
p4 <- plot_cty(class) + scale_fill_discrete(type = scale_fill_brewer)
plot_grid(p1, p2, p3, p4, labels = LETTERS[1:4], nrow = 2)
在上面的例子中(图 A-C
),我们在列表中根据离散数据的取值数目(因子的 level
)设置不同的配色。
在只有 1-2
个 level
时使用的是 skyblue
和 orange
,有 3
个 level
使用 Set2 配色,4-6
个 level
使用 Accent
配色。
更多推荐
所有评论(0)