专注系列化、高质量的R语言教程
本篇接上篇patchwork(上篇),目录如下:
0 示例图形
4 星号`*`
4.1 基本功能
4.2 优先级
4.3 识别嵌套水平
5 `&`操作符
0 示例图形
首先,参考官方文档[1],生成如下4个ggplot对象:
library(ggplot2)
p1 <- ggplot(mtcars) +
geom_point(aes(mpg, disp/100)) +
ggtitle('Plot 1')
p2 <- ggplot(mtcars) +
geom_point(aes(mpg, wt)) +
ggtitle('Plot 2')
p3 <- ggplot(mtcars) +
geom_point(aes(hp, wt, colour = mpg)) +
ggtitle('Plot 3')
p4 <- ggplot(mtcars) +
geom_bar(aes(gear)) +
facet_wrap(~cyl) +
ggtitle('Plot 4')
4 星号*
4.1 基本功能
*
可以统一向当前嵌套水平的所有子图添加代码。
先使用+
进行组图:
library(patchwork)
p1 + p2
![15e0cdb1be9a3a9779b64ac878c2a285.png](https://i-blog.csdnimg.cn/blog_migrate/fa2ec3eecd8573fd264428f25421c144.png)
使用*
统一设置子图的主题风格:
(p1 + p2) * theme_bw(base_family = "mono")
![c58ec8e315b5d27eac467503494bd82f.png](https://i-blog.csdnimg.cn/blog_migrate/3c9718f2e2557033c107483692cf6fc0.png)
对比使用+
的效果,它只会设置最后一个子图的主题:
(p1 + p2) + theme_bw(base_family = "mono")
![eee295c5c1b0b2344134de7bcae466a2.png](https://i-blog.csdnimg.cn/blog_migrate/9eaed2e4fc2673ecc3026a777f6094d3.png)
除了主题函数,*
后面也可以跟其他类型的函数,如几何图形函数:
(p1 + p2) *
geom_histogram(aes(mpg), bins = 15,
col = "black", alpha = 0.2) *
theme_bw(base_family = "mono")
![1e06c022e44ec68aefd324e21c87f869.png](https://i-blog.csdnimg.cn/blog_migrate/9c1895706c44bc82494310324b97eae2.png)
4.2 优先级
再来看以下例子:
p1 / p2 * theme_bw(base_family = "mono")
![159d9c6320fdd283e63bbc65d2d029e6.png](https://i-blog.csdnimg.cn/blog_migrate/b7117904f29d5aca3af6e21418807afc.png)
读者可能会疑惑:为何前面的例子
(p1 + p2) * theme_bw(base_family = "mono")
,+
部分需要加括号,而这里/
部分则不需要加括号?
这是因为*
的优先级与/
一样,并高于+
和-
,因此如果/
在前就会先运算/
,不需要额外加括号,即p1 / p2 * g = (p1 / p2) * g
。
这里
p1
和p2
表示子图,g
表示某段代码,如主题函数、几何图形函数等。
反之,如果*
在前就会先运算*
,即p1 * g / p2 = (p1 * g) / p2
:
p1 * theme_bw(base_family = "mono") / p2
![db1cc231a039ef60d67a1187867b871c.png](https://i-blog.csdnimg.cn/blog_migrate/df308bff63acc346ebd235ff159f3a2b.png)
*
的优先级高于+
,无论二者谁在前,都会先运算*
部分:
p1 * theme_bw(base_family = "mono") + p2
![6e530709357472d78747621887a75294.png](https://i-blog.csdnimg.cn/blog_migrate/197b1f1d76253c34be774de3ccf9862f.png)
p1 + p2 * theme_bw(base_family = "mono")
![5429aa465a3899ea9707cb5d70a0455e.png](https://i-blog.csdnimg.cn/blog_migrate/752442d3cf766c3d623a17df551b9588.png)
在编程语言中,星号*
常用来指代乘号,因此这个优先级顺序实际上和四则运算是一致的。
在前面的例子中,为了降低*
的优先级而使用括号,原理如下:
4.3 识别嵌套水平
*
只会作用于当前嵌套水平的子图,因此可以利用它来识别组图的嵌套水平。
(p1 + (p2 | p3) + p4) *
theme_bw(base_family = "mono")
![112ee48c39c86ba403fa3312ba1daa60.png](https://i-blog.csdnimg.cn/blog_migrate/4cd05f3b6939e57df253e84f302dd898.png)
p2
和p3
处于同一嵌套水平,然后作为整体与p1
、p4
处于更高嵌套水平,因此*
后的代码只作用于p1
、p4
。
读者可使用此方法识别和验证推文patchwork(上篇)中相关例子的嵌套水平。
5 &
操作符
&
操作符会将代码应用于所有嵌套水平的子图。
(p1 + (p2 | p3) + p4) &
theme_bw(base_family = "mono")
![dc2fb255b1834b88095e9e25d87bb710.png](https://i-blog.csdnimg.cn/blog_migrate/5d89b6c1e65f9233291bbc80d1ccdba9.png)
&
的优先级低于+
、-
、/
,并且不能位于它们之前
不加括号也可以实现上例的效果:
p1 + (p2 | p3) + p4 & theme_bw(base_family = "mono")
![df2e750be6dc20c83e84d20379ab44e4.png](https://i-blog.csdnimg.cn/blog_migrate/aeda8d8302518ec1a285b057a4dbecb1.png)
&
位于+
、-
、/
之前程序会报错:
## 以下代码均会报错
p1 & theme_bw(base_family = "mono") + p2
p1 & theme_bw(base_family = "mono") - p2
p1 & theme_bw(base_family = "mono") / p2
&
的优先级低于*
,但可以位于它之前
p1 + p2 & g1 * g2 = p1 + p2 & (g1 * g2)
:
p1 + p2 & theme_bw() * theme(text = element_text(family = "mono"))
![d4ce34a819a4b9ede4c87fe5bf02b5d5.png](https://i-blog.csdnimg.cn/blog_migrate/5e892c7ee6df7177fb746463ffbf2ce6.png)
p1 + p2 * g1 & g2 = p1 + (p2 * g1) & g2
:
p1 + p2 * theme_bw() & theme(text = element_text(family = "mono"))
![5bea61679048bc3b32e9a7e2e33369e1.png](https://i-blog.csdnimg.cn/blog_migrate/102bc2d99fdd02c3515705e6d929af60.png)
&
的优先级高于|
p1 & g | p2 = (p1 & g) | p2
:
p1 & theme_bw(base_family = "mono") | p2
![81041190fb2c7b93dc5a0805db7daac3.png](https://i-blog.csdnimg.cn/blog_migrate/6a2921330abb16bdfbf4ba389c273080.png)
p1 | p2 & g = p1 | (p2 & g)
:
p1 | p2 & theme_bw(base_family = "mono")
![85fa185987adb576ad435e95330f9159.png](https://i-blog.csdnimg.cn/blog_migrate/3ceb373a31a2b83ce30810bc318db22c.png)
至此,上篇结束,主要介绍的内容如下:
各种操作符的功能,它们的优先级顺序为:
()
>*
=/
>+
=-
>&
>|
;+
、-
、/
、|
单独连续使用只产生一个嵌套水平,-
每使用一次都会产生一个嵌套水平;操作符混合使用会增加嵌套水平;*
右侧的代码只应用于当前嵌套水平下的子图;&
右侧的代码应用于所有嵌套水平的子图。
敬请期待中篇。
参考资料
[1]
patchwork: Getting Started: https://mirrors.tuna.tsinghua.edu.cn/CRAN/web/packages/patchwork/vignettes/patchwork.html