ggplot2学习笔记10:分面(Facetting)详解

拈花ヽ惹草 提交于 2020-03-03 02:57:41

Chapter 7

Positioning



7.1 介绍(Introduction)

这部分讨论Positioning,特别是图层如何在页面上布局,以及坐标系统如何工作。有四个组件控制位置:

  • Position adjustments:调整层中重叠对象的位置;
  • Position scales:控制如何将数据中的值映射到图上的位置;

这部分主要介绍另外两个:

  • Facetting:分面是一种在页面上自动布局多个情节的机制。它将数据分成子集,然后在不同的分面中绘制每个子集;
  • Coordinate systems:控制两个独立的位置标度形成一个二维坐标系,最常见的坐标系是笛卡尔坐标系。

7.2 分面(Facetting)

每个小图都代表不同的数据子集。分面可以快速地分析数据各子集模式的异同。

本节讨论怎样较好微调分面,特别是和位置标度相关的方法。

  • facet_null():默认,无分面,单一图形
  • facet_wrap():封装型,本质上是一维,为节省空间封装成二维
  • facet_grid():网格型,生成一个由两个独立的部分组成的二维面板,面板的行和列可以通过变量来定义

两种绘图系统区别示意图

使用数据集:mpg数据集的一个子集(气缸数cylinders (4, 6, 8),驱动系统drive train (4, f),和6个classes

library(ggplot2)
mpg2 <- subset(mpg, cyl != 5 & drv %in% c("4", "f") & class != "2seater")
mpg2
#> # A tibble: 205 x 11
#>    manufacturer model      displ  year   cyl trans      drv     cty   hwy fl    class  
#>    <chr>        <chr>      <dbl> <int> <int> <chr>      <chr> <int> <int> <chr> <chr>  
#>  1 audi         a4           1.8  1999     4 auto(l5)   f        18    29 p     compact
#>  2 audi         a4           1.8  1999     4 manual(m5) f        21    29 p     compact
#>  3 audi         a4           2    2008     4 manual(m6) f        20    31 p     compact
#>  4 audi         a4           2    2008     4 auto(av)   f        21    30 p     compact
#>  5 audi         a4           2.8  1999     6 auto(l5)   f        16    26 p     compact
#>  6 audi         a4           2.8  1999     6 manual(m5) f        18    26 p     compact
#>  7 audi         a4           3.1  2008     6 auto(av)   f        18    27 p     compact
#>  8 audi         a4 quattro   1.8  1999     4 manual(m5) 4        18    26 p     compact
#>  9 audi         a4 quattro   1.8  1999     4 auto(l5)   4        16    25 p     compact
#> 10 audi         a4 quattro   2    2008     4 manual(m6) 4        20    28 p     compact
#> # ... with 195 more rows

7.2.1 封装分面(Facet wrap)

facet_wrap()函数先生成一个长的面板条块(有任意数目的变量生成),再将它封装在二维中

设置排列的参数:

  • ncolnrow:控制行列数,只需要设置一个;
  • as.table:是否以表格的形式显示布局,有True和False两个选项;
base <- ggplot(mpg2, aes(displ, hwy)) + 
  geom_blank() +   #这里可以使用其他几何对象,如geom_point()
  xlab(NULL) + 
  ylab(NULL)

base + facet_wrap(~class, ncol = 3)
base + facet_wrap(~class, ncol = 3, as.table = FALSE)

  • dir:控制环绕的方向horizontal或vertical,有 “h” 和 “v” 两个选项。
base + facet_wrap(~class, nrow = 3)
base + facet_wrap(~class, nrow = 3, dir = "v")

7.2.2 网格分面(Facet grid)

facet_grid()函数在二维网格中展示图形

在进行封面绘制时,需要设定哪些变量作为分面绘图的行,哪些变量作为列,规则如下:

  • 不进行分面:不使用函数facet_grid()或添加命令facet_null(),此时将会生成一个单独的面板
base + facet_null()

  • 一行多列:. ~ a
base + facet_grid(. ~ cyl)

  • 一列多行:b ~ .
base + facet_grid(drv ~ .)

  • 多行多列:a ~ b
base + facet_grid(drv ~ cyl)

7.2.3 标度控制(Controlling scales)

对于两种分面(wrap和grid),通过参数scales来控制面板位置标度的固定和自由:

  • scales = "fixed": x 和 y的标度在所有分面中都相同(默认)
  • scales = "free_x": x 的标度可变,y 固定
  • scales = "free_y": y 的标度可变,x 固定
  • scales = "free": x 和 y 的标度都可变

7.2.3.1 固定标度与自由标度

固定标度可以让我们在相同的基准上对子集进行比较:

mpg2 <- subset(mpg, cyl != 5 & drv %in% c("4", "f") & class != "2seater")
p <- ggplot(mpg2, aes(cty, hwy)) + 
  geom_abline() +
  geom_jitter(width = 0.1, height = 0.1) 
p + facet_wrap(~cyl)

自由标度可以帮助我们看到更多细节:

p + facet_wrap(~cyl, scales = "free")

7.2.3.2 一个案例

在变量y单位、数量级不同时,单独固定x轴,不限制y轴对数据的可视化将很直观。

economics数据集为例:

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变量分面
ggplot(economics_long, aes(date, value)) + 
  geom_line() + 
  facet_wrap(~variable, scales = "free_y", ncol = 1)

注意facet_grid()存在一个限制:网格分面中每一列共享一个x轴,而每一行共享一个y轴,同列中的所有面板都必须具有相同的x标度,并且同行中的所有面板都必须具有相同的y标度。

facet_grid()中,有个叫space的附加参数,当space = "free"时,每行的高度和该行的标度范围一致,这对分类标度很有用:

reorder()函数使得模型(model)和生产商(manufacturer)按城市油耗英里数(cty)重新排序。

mpg2 <- subset(mpg, cyl != 5 & drv %in% c("4", "f") & class != "2seater")
mpg2$model <- reorder(mpg2$model, mpg2$cty)
mpg2$manufacturer <- reorder(mpg2$manufacturer, -mpg2$cty)
ggplot(mpg2, aes(cty, model)) + 
  geom_point() + 
  facet_grid(manufacturer ~ ., scales = "free", space = "free") +
  theme(strip.text.y = element_text(angle = 0))

7.2.4 缺失分面变量(Missing facetting variables)

先设置俩数据框,df1和df2,其中df1中有分面变量gender,而df2里没有这个变量。这时我们可以通过增加df2的图层(并且把它放在前面,要不就盖住df1的数据点了),让df2中的数据出现在每个分面中。

df1 <- data.frame(x = 1:3, y = 1:3, gender = c("f", "f", "m"))
df2 <- data.frame(x = 2, y = 2)

ggplot(df1, aes(x, y)) + 
  geom_point(data = df2, colour = "red", size = 4) + 
  geom_point(size = 2) + 
  facet_wrap(~gender)

7.2.5 分组和分面(Grouping vs. Facetting)

通过调整颜色、形状等图形属性可以来分组,而分面则是另一种分组方法。根据子集相对位置的不同,可以有选择的使用这两种绘图技巧:

  • 通过分面分组:每个组在其各自的面板中相距很远,并且组之间没有重叠,但很难分辨细微差异;
  • 通过**美学(图形属性)**分组:各组数据彼此靠近并且可能重叠,但很容易分辨细微差异。

通过创建一些随机数组举个栗子:

df <- data.frame(
  x = rnorm(120, c(0, 2, 4)),  #生成均值分别为0,2,4120个正态分布随机数
  y = rnorm(120, c(1, 2, 1)),
  z = letters[1:3]
)

ggplot(df, aes(x, y)) + 
  geom_point(aes(colour = z))

ggplot(df, aes(x, y)) + 
  geom_point() + 
  facet_wrap(~z)

其他方法:

  • 利用dplyr分类汇总:

    准备工作

    需要加载两个包magrittrdplyr,要使用其中函数

    • magrittr包:R语言高效的管道操作magrittr(点我了解

    ​ 关于%>%:magrittr包被定义为一个高效的管道操作工具包,通过管道的连接方式,让数据或表达式的传递更高效,使用操作符%>%,可以直接把数据传递给下一个函数调用或表达式。magrittr包的主要目标有2个,第一是减少代码开发时间,提高代码的可读性和维护性;第二是让你的代码更短,再短,短短短…

    • dplyr包:R语言数据处理利器——dplyr简介(点我了解

    安装加载

    install.packages(c("magrittr", "dplyr"))
    library(magrittr)
    library(dplyr)
    

在前边创建的df数据集基础上,利用管道操作符%>%创建新的数据集df_sum

group_by()用于对数据集按照给定变量分组,返回分组后的数据集。对返回后的数据集使用以上介绍的函数时,会自动的对分组数据操作:

df_sum <- df %>% 
  group_by(z) %>% 
  summarise(x = mean(x), y = mean(y)) %>%
  rename(z2 = z) 
df_sum  #均值
#> # A tibble: 3 x 3
#>   z2         x     y
#>   <fct>  <dbl> <dbl>
#> 1 a     -0.219 0.918
#> 2 b      2.04  1.82 
#> 3 c      3.92  1.28 

接下来创建散点分面图:第一个图层映射df数据;第二个图层映射df_sum数据,并设置颜色等图形属性;最后按照z分面:

ggplot(df, aes(x, y)) + 
  geom_point() + 
  geom_point(data = df_sum, aes(colour = z2), size = 4) + 
  facet_wrap(~z)

  • 将所有数据放在每个面板的背景中,再突出显示所需分组数据(与[7.2.4](# 7.2.4 缺失分面变量(Missing facetting variables))方法原理一致):

dplyr数据包中的select()参数,选择子数据集df2

df2 <- dplyr::select(df, -z)  #-z表示删除df数据集中的变量z

ggplot(df, aes(x, y)) + 
  geom_point(data = df2, colour = "grey70") +
  geom_point(aes(colour = z)) + 
  facet_wrap(~z)

7.2.6 连续变量(Continuous variables)

连续变量也可以用来分面,但必须首先离散化它们。ggplot2提供了三个函数:

  • cut_interval(x, n):将数据分成n个相同长度的部分
  • cut_width(x, width):将数据按宽度划分
  • cut_number(x, n = 10):将数据划分为n个相同数目点的部分,每个分面上点数为n

如下图所示:

# Bins of width 1
mpg2$disp_w <- cut_width(mpg2$displ, 1)
# Six bins of equal length
mpg2$disp_i <- cut_interval(mpg2$displ, 6)
# Six bins containing equal numbers of points
mpg2$disp_n <- cut_number(mpg2$displ, 6)

plot <- ggplot(mpg2, aes(cty, hwy)) +
  geom_point() +
  labs(x = NULL, y = NULL)
plot + facet_wrap(~disp_w, nrow = 1)

plot + facet_wrap(~disp_i, nrow = 1)

plot + facet_wrap(~disp_n, nrow = 1)


参考资料:

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!