这节开始学习ggplot2图形语法中另外两个重要元素:分面。
分面
在美学映射那一节中,当我们需要把大于两个变量映射到图形中时,x轴和y轴就已经不够用了,需要通过形状和颜色等可区分的形式来代表新增的变量,但是一味的在一张图中增加多种映射会导致图上的信息密度过高,可读性差,这时分面的作用就体现出来了。
单变量分面
对于单个变量的分面,可以用函数facet_wrap()
,它的第一个参数是一个表达式,用~ variable
来表示,就是在~
后加上变量名,注意这里的变量需要是离散的:
library(ggplot2)
ggplot(data = mpg)
geom_point(mapping = aes(x = displ, y = hwy))
facet_wrap(~ class, nrow = 2)
双变量分面
对于两个变量,可以用函数fact_grid()
,用法和fact_wrap()
类似,用variable1 ~ variable2
来表示:
ggplot(data = mpg)
geom_point(mapping = aes(x = displ, y = hwy))
facet_grid(drv ~ cyl)
练习
- What happens if you facet on a continuous variable? 用连续变量分面试试:
ggplot(data = mpg)
geom_point(mapping = aes(x = model, y = hwy))
facet_grid( ~ displ)
直接用连续变量分面,可以看到因为连续变量的数值较多,导致分面的图形拥挤完全无法观看。
那么如果连续变量较少呢?如下:
代码语言:text复制ggplot(data = mpg[1:15, ])
geom_point(mapping = aes(x = model, y = hwy))
facet_grid( ~ displ)
现在图形不影响观看了,但是这组图形经过分面有没有增加它所包含的信息量?其实并不直观,因为针对连续变量,一般是想看到它连续变化时的影响,如下图,就可以直观看出不同型号的汽车的每加仑高速里程并不是一直和发动机排量成正比的:
代码语言:text复制ggplot(data = mpg[1:15, ])
geom_point(mapping = aes(x = displ, y = hwy))
facet_grid( ~ model)
2.What do the empty cells in plot with facet_grid(drv ~ cyl)
mean? How do they relate to this plot?
先看下分面后的图:
代码语言:text复制ggplot(data = mpg)
geom_point(mapping = aes(x = drv, y = cyl))
facet_grid(drv ~ cyl)
有3张空图,那再看不分面的:
代码语言:text复制ggplot(data = mpg)
geom_point(mapping = aes(x = drv, y = cyl))
可以看到三种传动类型(drv)都没有包含7个汽缸(cyl)的车,5个汽缸的也只有前驱(f)车型有,所以这些数据实际是缺失的:
代码语言:text复制table(mpg$drv, mpg$cyl)
代码语言:text复制##
## 4 5 6 8
## 4 23 0 32 48
## f 58 4 43 1
## r 0 0 4 21
用facet_grid(drv ~ cyl)
分面的时候,可以看到整组图(上边和右边灰色框)是以cyl为x轴,drv为y轴的,由于7个汽缸对应的全是空图,直接被剔除掉。
3.What plots does the following code make? What does .
do?
直接运行:
代码语言:text复制ggplot(data = mpg)
geom_point(mapping = aes(x = displ, y = hwy))
facet_grid(drv ~ .)
ggplot(data = mpg)
geom_point(mapping = aes(x = displ, y = hwy))
facet_grid(. ~ cyl)
可以看到第一张分面变量在右边,第二张在上边,不加.
的话:
ggplot(data = mpg)
geom_point(mapping = aes(x = displ, y = hwy))
facet_grid(drv ~ )
代码语言:text复制## Error: <text>:3:20: unexpected ')'
## 2: geom_point(mapping = aes(x = displ, y = hwy))
## 3: facet_grid(drv ~ )
## ^
会报错,所以.
的作用就是相当于一个空白变量,这样当要把单个变量分面到y轴的时候就可以用.
来占位了。
4.Take the first faceted plot in this section: What are the advantages to using faceting instead of the colour aesthetic? What are the disadvantages? How might the balance change if you had a larger dataset?
代码语言:text复制ggplot(data = mpg)
geom_point(mapping = aes(x = displ, y = hwy))
facet_wrap(~ class, nrow = 2)
代码语言:text复制ggplot(data = mpg)
geom_point(mapping = aes(x = displ, y = hwy, color = class))
分面替代颜色映射的优势就是可以清晰呈现各个分面变量的相关信息,如上图车型(class)用颜色映射时就很难分清各车型的发动机排量(displ)和每加仑高速里程(hwy)的关系;而要分面的变量所含的种类较多时,就会导致分面出的图形太多,就如上面用连续变量分面一样。
5.Read ?facet_wrap
. What does nrow
do? What does ncol
do? What other options control the layout of the individual panels? Why doesn't facet_grid()
have nrow
and ncol
arguments?
nrow
和ncol
很好理解,分面图形的排列行数和列数;facet_grid()
没有这些参数,但是有rows
和cols
,可以运行示例代码查看:
ggplot(mpg, aes(displ, cty))
geom_point()
facet_grid(cols = vars(drv))
代码语言:text复制ggplot(mpg, aes(displ, cty))
geom_point()
facet_grid(rows = vars(drv))
代码语言:text复制ggplot(mpg, aes(displ, cty))
geom_point()
facet_grid(vars(drv), vars(cyl))
其实就是把变量指定分面到行或列。
6.When using facet_grid()
you should usually put the variable with more unique levels in the columns. Why?
将有更多水平的变量放在列会比放在行更具可读性:
代码语言:text复制ggplot(data = mpg)
geom_point(mapping = aes(x = displ, y = hwy))
facet_grid(drv ~ trans)
代码语言:text复制ggplot(data = mpg)
geom_point(mapping = aes(x = displ, y = hwy))
facet_grid(trans ~ drv)
参考资料:
https://r4ds.had.co.nz/index.html