5 图层
5.1 图形部件
data
aes:着重说下这部分。
-
aes()美学映射,就是将数据集中的变量数据映射(关联)到相应的图形属性上。
常用的图形属性有color、size、shape、alpha等。
需要特别注意的是,映射不是直接出现在图形中的颜色、外形等设定的特定值,而是建立数据与图形的联系,所以要为图形指定特定值(如设定点为红色等),是不能直接放在
aes()中的。color、size等图形属性直接映射到数据集的分类变量,可以实现不同分组用不同美学来区分。
- geom:几何对象,即确定我们想画什么图。更多集合形状推荐阅读这里。
有很多关于r语言绘图的图库网站,The R Graph Gallery。网站给出了常用图形的R代码,可以查阅并了解每种图形使用场景和优缺点。
Aesthetic specifications是
ggplot2的美学映射官方文档,可以查阅所有可能的美学映射方式,包括点、线、多边形、文字等。ggplot2 extensions是
ggplot2的扩展包集合网站,部分默认没有的几何对象,可以先参阅此处查找,获取已经有人实现了:)
以下4~10,我们挑不太熟悉的细说。
- stats: 统计变换。
- coord: 坐标系统。
- facet: 分面。
- save: 保存图片。
5.2 统计变换
为图形计算新值的运算过程,称为统计变换。在条形图、直方图、频数图、箱线图中均有类似过程
每一个几何对象都有一个默认的统计变换,我们可以通过检查
stat参数的默认值来了解几何对象使用了哪种统计变换。例如,?geom_bar显示stat的默认值为”count",这意味着geom_bar()使用stat_count()。stat_count()的说明文档与geom_bar()位于同一页面。若向下滚动页面,名为”Computed variables”的章节会说明其会计算两个新变量:count和prop。大多时候,我们不需要关注统计变换,但有3种情况可能需要显示的使用统计变换。
- 可能需要覆盖默认的统计变换方式。在以下代码中,我们将
geom_bar()的统计方法从默认的计数(count)改为直接映射(identity)。这使得我们可以将条形的高度直接对应到y变量的原始数值上。
- 可能希望覆盖从转换变量到美学属性的默认映射。例如,我们可能希望显示比例条形图,而非计数条形图。在每个几何对象的
help页面中,名为”Computed variables”的章节会说明其能够使用after_stat()函数计算相应的新的变量。
-
after_stat(): 顾名思义,这个函数是 ggplot2 中用于访问 统计变换(stat)后生成的临时变量” 的核心函数,作用是在美学映射(aes())中引用 ggplot2对原始数据做统计计算后产生的新变量。(这些变量不存在于原始数据中,仅在绘图时临时生成)。简单理解:-
原始数据变量(如渔业数据的体长/水温):直接在
aes()中引用即可,例如:aes(x = 体长); -
统计变换后变量(如直方图的计数count、箱线图的中位数middle、密度图的密度density):必须用
after_stat(变量名)引用,例如aes(fill = after_stat(count))。
-
原始数据变量(如渔业数据的体长/水温):直接在
after_stat()?
ggplot2中的很多图层(如geom_histogram/geom_boxplot/geom_smooth)会自动对原始数据做统计变换:比如用geom_histogram()画鱼类体长直方图时,ggplot2 会先把体长分成若干 “区间(bin)”,再计算每个区间的 “样本数(count)”:这个count不是原始数据列,而是统计变换后生成的临时变量,必须通过after_stat(count)才能访问。
# group = 1,强制将所有 cut 类别归为同一个分组,此时 prop 计算的是 “每个 cut 的数量占所有钻石总数的比例”,才能得到正确的占比结果。
ggplot(diamonds, aes(x = cut, y = after_stat(prop), group = 1)) +
geom_bar()
以上代码中的group = 1参数是 ggplot2 中强制将所有数据归为”同一个分组”的核心语法,如果不设置,则ggplot 按 x 轴分类分组,最终的计算结果是每个组内的比例均为100%(因为各自占各自分组数量的占比100%),所有柱子高度都是1,完全错误。
- 我们可能希望在代码中更突出地展示统计变换过程。例如,可以使用
stat_summary()(该函数会为每个独立 x 值汇总对应的 y 值)来强调我们正在计算的统计摘要:
ggplot2 提供了超过 20 种统计变换供您使用。每种统计变换都是一个函数,因此我们可以通过常规方式获取帮助。ggplot(diamonds) +
stat_summary(
aes(x = cut, y = depth),
fun.min = min,
fun.max = max,
fun = median
)
5.3 图例系统
具体的图例的设置可参看 小节 C.3.5。
guides()函数族用于控制图例外观:
guide_colorbar(): 连续的颜色
guide_legend(): 离散变量 (shapes, colors)
guide_axis(): 控制图例坐标的字体和间隔,增加第二图例坐标轴
guide_bins(): 在图例中创建值的“bin”
guide_colorsteps(): 使颜色条离散化
5.3.1 案例
library(tidyverse)
ggplot(
mpg,
aes(
x = displ,
y = hwy,
color = factor(cyl)
)
) +
geom_point() +
guides(
color = guide_legend(
title = "my legend",
title.position = "top",
title.vjust = 5,
label.position = "left",
label.theme = element_text(
size = 15,
face = "italic",
color = "red",
angle = 0
),
keywidth = 5, # 设定bin的宽度
reverse = TRUE # 翻转图例排序
)
)
ggplot(
mpg,
aes(
x = displ,
y = hwy,
color = cyl
)
) +
geom_point() +
guides(
color = guide_colorbar(
title = "CYL",
label.position = "left", # label.**系列参数设定坐标外观
label.theme = element_text(
size = 18,
color = "steelblue",
vjust = 1
),
ticks.linewidth = 2, # tick.**系列参数设定刻度
# direction = "horizontal"or"vertical" 图例方向,水平、垂直
)
)
5.3.2 删除其中一个图例
ggplot(
mpg,
aes(
x = displ,
y = hwy,
color = class,
size = cyl
)
) +
geom_point() +
# 如果想删除size图例
guides(size = "none") # remove
# 或guides(size = guide_none())5.3.3 合并图例
library(tidyverse)
library(palmerpenguins)
ggplot(
penguins,
aes(
x = bill_length_mm,
y = bill_depth_mm,
color = body_mass_g,
size = body_mass_g
)
) +
geom_point(alpha = 0.6) +
scale_color_viridis_c()
上图中,color 和 size都使用了Body_mass_g映射,为图形美观,我们可以将两者合并
ggplot(
penguins,
aes(
x = bill_length_mm,
y = bill_depth_mm,
color = body_mass_g,
size = body_mass_g
)
) +
geom_point(alpha = 0.6) +
scale_color_viridis_c() +
guides(color = guide_legend()) # 其实就是保留其中一个图例
5.3.4 最后一个例子
mtcars %>%
as_tibble() %>%
ggplot(aes(
x = wt,
y = mpg,
shape = factor(vs),
color = hp
)) +
geom_point(size = 3) +
colorspace::scale_color_binned_sequential(
palette = "Dark Mint" # 更换图形主题颜色
) +
labs(
x = "Weight (1000 lbs)",
y = "Miles per gallon",
title = "Motor Trend Car Road Tests",
shape = "Engine",
color = "Horsepower"
) + # 更改图形和图例标题
theme(
text = element_text(size = 18, color = "white"),
rect = element_rect(fill = "black"), # 图形背景颜色
panel.background = element_rect(fill = "black"), # 画板颜色
legend.key = element_rect(fill = "black"), # 分散变量图例背景
axis.text = element_text(color = "white"), # 坐标轴字体
plot.title.position = "plot",
plot.margin = margin(10, 10, 10, 10) # 图形距离边的距离
) +
guides(
shape = guide_legend(override.aes = list(color = "white")) # 离散型图例颜色
)
5.4 分面
facet_wrap()适用于一个单个变量的多个分面。facet_grid()适用于有两个离散变量且其组合均在数据中存在。符号
~:
-
facet_wrap( ~ B):基于变量B分面。 -
facet_grid(A ~ B):变量 ~ 变量,其中A可以是两个变量相加(即变量+变量~变量).
library(nycflights13)
library(patchwork)
p1 <- ggplot(data = weather, aes(x = temp)) +
geom_histogram(binwidth = 5, color = "white") +
facet_wrap(~month)
p2 <- ggplot(data = weather, aes(x = temp, y = humid)) +
geom_point() +
facet_grid( ~ month, scales = "free")
p1 / p2
- 默认情况下,每个分面的
x轴和y轴共享相同的刻度和范围。当需要跨分面比较数据时这很有用,但若想更好地展示各分面内部的关系则会受限。在分面函数中设置scales参数为"free_x"和 可允许各列使用不同的x轴刻度,"free_y"可允许各行使用不同的y轴刻度,"free"则可同时允许两者采用独立刻度。
p1 <- ggplot(mpg, aes(displ, hwy)) +
geom_point() +
facet_grid(drv ~ cyl) +
labs(title = "Without free")
p2 <- ggplot(mpg, aes(displ, hwy)) +
geom_point() +
facet_grid(drv ~ cyl, scale = "free") +
labs(title = "With free")
p1 / p2
- 仔细观察以下两个图形,第一张图表能够更直观地对比不同传动系统车型(
drv)的发动机排量(displ),原因在于图表的各分面共享了用于绘制发动机排量的坐标轴。这说明,如果分析目标是基于某一特定变量进行数据对比,那么就应当将该变量设置在共享坐标轴上。
ggplot(mpg, aes(x = displ)) +
geom_histogram() +
facet_grid(drv ~ .) 
ggplot(mpg, aes(x = displ)) +
geom_histogram() +
facet_grid(. ~ drv)
5.5 总结
从本章中应汲取的重要一课是:当你需要
ggplot2未提供的几何对象时,最好先查看是否已有其他人通过创建提供该几何对象的ggplot2扩展包解决了你的问题。更详尽的主题设置可参看 附录 C。
