R 数据可视化 —— ggplot 图例设置
前言
坐标轴和图例被统称为 guides,通常使用标度函数来控制,如 limits, breaks 和 labels 参数。
坐标轴与图例很类似,例如,坐标轴的轴标签与图例的标题都是对应到标度函数的 name 参数,而图例的标识(key label)和轴的刻度标签对应于标度函数的 break 参数
除了可以在每个标度函数中分开设置,也可以使用 guides() 函数来进行统一设置,两种设置方式是等价的。
例如,下面的设置方式是等价的
dat <- data.frame(x = 1:5, y = 1:5, p = 1:5, q = factor(1:5),
r = factor(1:5))
p <- ggplot(dat, aes(x, y, colour = p, size = q, shape = r)) + geom_point()
p1 <- p + guides(colour = "colorbar", size = "legend", shape = "legend")
p2 <- p + guides(colour = guide_colorbar(), size = guide_legend(),
shape = guide_legend())
p3 <- p +
scale_colour_continuous(guide = "colorbar") +
scale_size_discrete(guide = "legend") +
scale_shape(guide = "legend")
再比如,删除某一图例或整合所有图例
# 删除图例
p1 <- p + guides(colour = "none")
p2 <- p + guides(colour = "colorbar",size = "none")
# 整合图例
p3 <- p + guides(colour = guide_legend("title"), size = guide_legend("title"),
shape = guide_legend("title"))
# 与上面的代码等价
g <- guide_legend("title")
p4 <- p + guides(colour = g, size = g, shape = g)
plot_grid(p1, p2, p3, p4, labels = LETTERS[1:4], ncol = 2)
1. 图例符号
在之前的绘制中,通常图例会根据几何对象来生成图例。例如上图中,点图的图例符号也是点。
我们可以为 key_glyph 参数设置不同的
draw_key_*()
函数来自定义图例符号,其中
*
号表示的是各种符号。
p <- ggplot(economics, aes(date, psavert, color = "savings rate"))
p1 <- p + geom_line()
# 通过指定字符串名称
p2 <- p + geom_line(key_glyph = "timeseries")
# 或者对应的函数名
p3 <- p + geom_line(key_glyph = draw_key_timeseries)
# 其他形状
p4 <- p + geom_line(key_glyph = draw_key_rect)
plot_grid(p1, p2, p3, p4, labels = LETTERS[1:4],
nrow = 2)
2. 颜色条
简单的颜色条可以通过 scale_fill 和 scale_colour 的 guide 参数来设置
df <- expand.grid(X1 = 1:10, X2 = 1:10)
df$value <- df$X1 * df$X2
p1 <- ggplot(df, aes(X1, X2)) + geom_tile(aes(fill = value))
# 使用字符串名称
p1 + scale_fill_continuous(guide = "colourbar")
# 或者对应的函数
p1 + scale_fill_continuous(guide = guide_colourbar())
相当于下面的代码
p1 + guides(fill = guide_colourbar())
guide_colourbar 函数的参数非常多
guide_colourbar(
title = waiver(),
title.position = NULL,
title.theme = NULL,
title.hjust = NULL,
title.vjust = NULL,
label = TRUE,
label.position = NULL,
label.theme = NULL,
label.hjust = NULL,
label.vjust = NULL,
barwidth = NULL,
barheight = NULL,
nbin = 300,
raster = TRUE,
frame.colour = NULL,
frame.linewidth = 0.5,
frame.linetype = 1,
ticks = TRUE,
ticks.colour = "white",
ticks.linewidth = 0.5,
draw.ulim = TRUE,
draw.llim = TRUE,
direction = NULL,
default.unit = "line",
reverse = FALSE,
order = 0,
available_aes = c("colour", "color", "fill"),
我们对部分参数进行说明,如设置颜色条的大小、删除标签或刻度、调整标签的位置以及设置标签的主题
# 设置大小
p2 <- p1 + guides(fill = guide_colourbar(barwidth = 0.5, barheight = 10))
# 删除标签
p3 <- p1 + guides(fill = guide_colourbar(label = FALSE))
# 删除刻度
p4 <- p1 + guides(fill = guide_colourbar(ticks = FALSE))
# 调整标签位置
p5 <- p1 + guides(fill = guide_colourbar(label.position = "left"))
# 设置标签主题
p6 <- p1 + guides(fill = guide_colourbar(label.theme = element_text(colour = "blue", angle = 0)))
plot_grid(p1, p2, p3, p4, p5, p6, labels = LETTERS[1:6],
nrow = 3)
设置颜色条每个刻度间的分箱个数,分箱越多,颜色条看起来越平滑
# 颜色条的分箱个数,越大越平滑
p7 <- p1 + guides(fill = guide_colourbar(nbin = 3))
p8 <- p1 + guides(fill = guide_colourbar(nbin = 100))
plot_grid(p7, p8, labels = LETTERS[1:2])
如果存在多个图例,可以分别对每个图例进行独立的设置
p2 <- p1 + geom_point(aes(size = value))
# 多个图例,可以分开独立控制
p3 <- p2 +
scale_fill_continuous(guide = "colourbar") +
scale_size(guide = "legend")
# 或者使用字符串名称
p3 <- p2 + guides(fill = "colourbar", size = "legend")
p4 <- p2 +
scale_fill_continuous(guide = guide_colourbar(direction = "horizontal")) +
scale_size(guide = guide_legend(direction = "vertical"))
plot_grid(p3, p4, labels = LETTERS[1:2])
3. 基本图例设置
也可以使用 guide_legend 函数来设置图例的样式,该函数也有很多参数可供选择
guide_legend(
title = waiver(),
title.position = NULL,
title.theme = NULL,
title.hjust = NULL,
title.vjust = NULL,
label = TRUE,
label.position = NULL,
label.theme = NULL,
label.hjust = NULL,
label.vjust = NULL,
keywidth = NULL,
keyheight = NULL,
direction = NULL,
default.unit = "line",
override.aes = list(),
nrow = NULL,
ncol = NULL,
byrow = FALSE,
reverse = FALSE,
order = 0,
例如,下面的代码只绘制了一个简单的图例
df <- expand.grid(X1 = 1:10, X2 = 1:10)
df$value <- df$X1 * df$X2
p1 <- ggplot(df, aes(X1, X2)) + geom_tile(aes(fill = value))
p1 + scale_fill_continuous(guide = guide_legend())
我们可以为它设置各种样式,如
# 设置图例标题的位置
p2 <- p1 + guides(fill = guide_legend(title = "LEFT", title.position = "left"))
# 使用 element_text 设置图例标题的样式
p3 <- p1 + guides(fill =
guide_legend(
title.theme = element_text(
size = 15,
face = "italic",
colour = "red",
angle = 0
# 设置标签的位置
p4 <- p1 + guides(fill = guide_legend(label.position = "left", label.hjust = 1))
# 设置标签的样式
p5 <- p1 + scale_fill_continuous(breaks = c(5, 10, 15),
labels = paste("long", c(5, 10, 15)),
guide = guide_legend(
direction = "horizontal",
title.position = "top",
label.position = "bottom",
label.hjust = 0.5,
label.vjust = 1,
label.theme = element_text(angle = 90)
plot_grid(p2, p3, p4, p5, labels = LETTERS[1:4], nrow = 2)
也可以覆盖原理的属性映射
p3 <- ggplot(mtcars, aes(vs, am, colour = factor(cyl))) +
geom_jitter(alpha = 1/5, width = 0.01, height = 0.01)
# override.aes overwrites the alpha
p4 <- p3 + guides(colour = guide_legend(override.aes = list(alpha = 1)))
plot_grid(p3, p4, labels = LETTERS[1:2])
在图 A 中,点的透明度太低了,看起来挺费劲的。然后在图 B 中,我们将透明度 alpha 设置为 1,更容易分辨不同类型的点。
对于某些图,由于类别太多导致图例非常的长,例如
df <- data.frame(x = 1:20, y = 1:20, color = letters[1:20])
p <- ggplot(df, aes(x, y)) +
geom_point(aes(colour = color))
我们可以限制图例的行列数
# 限制行列的数目
p1 <- p + guides(col = guide_legend(nrow = 8))
p2 <- p + guides(col = guide_legend(ncol = 8))
p3 <- p + guides(col = guide_legend(nrow = 8, byrow = TRUE))
# 将顺序反转
p4 <- p + guides(col = guide_legend(reverse = TRUE))
plot_grid(p1, p2, p3, p4, labels = LETTERS[1:4], ncol = 2)
让图例看起来更好看些。
我们在图 D 中,设置 reverse = TRUE 可以将标签顺序进行反转
4. 基本坐标轴设置
坐标轴的设置通常与
scale_(x|y)_continuous()
和
scale_(x|y)_discrete()
两个标度函数搭配使用
guide_axis(
title = waiver(),
check.overlap = FALSE,
angle = NULL,
n.dodge = 1,
order = 0,
position = waiver()
例如
p <- ggplot(mpg, aes(cty * 100, hwy * 100)) +
geom_point()
# 设置标签的行数(如果要设置列,需要传入一个向量)
p1 <- p + scale_x_continuous(guide = guide_axis(n.dodge = 2))
# 设置标签的角度
p2 <- p + guides(x = guide_axis(angle = 90))
# 复制一个轴
p3 <- p + guides(x = guide_axis(n.dodge = 2), y.sec = guide_axis())
plot_grid(p, p1, p2, p3, labels = LETTERS[1:4], ncol = 2)
5. 分箱图例
分箱图例使用 guide_bins 函数来设置,它是 guide_legend() 的分箱版本,通常需要和分箱的标度函数一起使用
如果你想要将其搭配离散型数据使用,需要确保离散数据的 level 必须遵从 base::cut 函数的命名规则,即名称必须为
(<lower>, <upper>]
形式
示例
p <- ggplot(mtcars) +
geom_point(aes(disp, mpg, size = hp)) +
scale_size_binned()
# 删除轴或样式
p1 <- p + guides(size = guide_bins(axis = FALSE))
# 显示分箱区间
p2 <- p + guides(size = guide_bins(show.limits = TRUE))
# 设置轴的箭头
p3 <- p + guides(size = guide_bins(
axis.arrow = arrow(length = unit(1.5, 'mm'), ends = 'both')
# 默认会尽可能将图例合并
p4 <- ggplot(mtcars) +
geom_point(aes(disp, mpg, size = hp, colour = hp)) +
scale_size_binned() +
scale_colour_binned(guide = "bins")
plot_grid(p1, p2, p3, p4, labels = LETTERS[1:4], ncol = 2)
6. 分箱颜色条
分箱颜色条 guide_coloursteps 是 guide_colourbar() 的分箱版,它将断点之间的区域显示为一个固定的颜色
例如,
df <- expand.grid(X1 = 1:10, X2 = 1:10)
df$value <- df$X1 * df$X2
p <- ggplot(df, aes(X1, X2)) + geom_tile(aes(fill = value))
p1 <- p + scale_fill_binned()
# 默认是等间距的断点,可以自定义断点
p2 <- p + scale_fill_binned(breaks = c(10, 25, 50))
# 根据区间的数据占比显示长度
p3 <- p + scale_fill_binned(
breaks = c(10, 25, 50),
guide = guide_coloursteps(even.steps = FALSE)
# 是否显示所有刻度(外围的刻度)
p4 <- p + scale_fill_binned(guide = guide_coloursteps(show.limits = TRUE))
plot_grid(p1, p2, p3, p4, labels = LETTERS[1:4], ncol = 2)
7. 设置次轴
sec_axis 和 dup_axis 函数与位置标度一起使用,来创建与主轴相对的次轴。
副轴必须基于主轴的一对一变换
sec_axis(
trans = NULL,
name = waiver(),
breaks = waiver(),
labels = waiver(),
guide = waiver()
dup_axis(
trans = ~.,
name = derive(),
breaks = derive(),
labels = derive(),
guide = derive()
sec_axis() 需要一个转换函数传递给 trans 参数,其他所有设置可以使用 derive() 从主轴继承
dup_axis() 创建一个主轴的拷贝作为次轴
示例
p <- ggplot(mtcars, aes(cyl, mpg)) +
geom_point()
# 创建一个简单的次轴
p1 <- p + scale_y_continuous(sec.axis = sec_axis(~ . + 10))
# 从主轴中继承名称
p2 <- p + scale_y_continuous("Miles/gallon", sec.axis = sec_axis(~ . + 10, name = derive()))
# 复制一份主轴
p3 <- p + scale_y_continuous(sec.axis = dup_axis())
# 设置转换函数
p4 <- p + scale_y_continuous(sec.axis = ~ .^2)
plot_grid(p1, p2, p3, p4, labels = LETTERS[1:4],
nrow = 2)
创建时间次轴
df <- data.frame(
dx = seq(as.POSIXct("2012-02-29 12:00:00",
tz = "UTC",
format = "%Y-%m-%d %H:%M:%S"
length.out = 10, by = "4 hour"
price = seq(20, 200000, length.out = 10)
ggplot(df, aes(x = dx, y = price)) + geom_line() +
scale_x_datetime("Date", date_labels = "%b %d",
date_breaks = "6 hour",
sec.axis = dup_axis(name = "Time of Day",