查看原文
其他

ggplot 分面绘图一网打尽

JunJunLab 老俊俊的生信笔记 2022-08-15

点击上方关注我们








叨叨




今天介绍一下 ggplot 函数里面的 facet_wrapfacet_grid 函数,不是你图画的不好或者不好看,而是你对 ggplot 了解不够多。

facet_wrap 函数意为封装函数,有点像 一维图形排列 的感觉,将一个个图形往后排成一行,不够另起一行。

facet_grid 函数意为网格,有点绘制 几行几列 的表格的意思。下面我们详细介绍这两个函数。




我开始表演




1、facet_wrap


我们用 R 自带的 钻石数据集 进行测试:

# 加载R包
library(ggplot2)
library(ggprism)
# 加载内置数据
data("diamonds")
# 查看数据
head(diamonds,3)
# A tibble: 3 x 10
  carat cut     color clarity depth table price     x     y     z
  <dbl> <ord>   <ord> <ord>   <dbl> <dbl> <int> <dbl> <dbl> <dbl>
1  0.23 Ideal   E     SI2      61.5    55   326  3.95  3.98  2.43
2  0.21 Premium E     SI1      59.8    61   326  3.89  3.84  2.31
3  0.23 Good    E     VS1      56.9    65   327  4.05  4.07  2.31

可以看到是一个 tibble 格式,看看变量分类有哪些:

table(diamonds$cut)
     Fair      Good Very Good   Premium     Ideal
     1610      4906     12082     13791     21551
table(diamonds$color)
    D     E     F     G     H     I     J
 6775  9797  9542 11292  8304  5422  2808
table(diamonds$clarity)
   I1   SI2   SI1   VS2   VS1  VVS2  VVS1    IF
  741  9194 13065 12258  8171  5066  3655  1790

查看facet_wrap参数:

Usage
facet_wrap(
  facets,
  nrow = NULL,
  ncol = NULL,
  scales = "fixed",
  shrink = TRUE,
  labeller = "label_value",
  as.table = TRUE,
  switch = NULL,
  drop = TRUE,
  dir = "h",
  strip.position = "top"
)

先画好我们的基本图形:

p <- ggplot(data = diamonds,aes(x = carat,y = price)) +
  geom_point(aes(color = cut),size = 2,alpha = .75) +
  theme_prism(base_size = 14,border = T) +
  theme_bw()

默认分面:

p + facet_wrap(~cut)

参数 nrowncol 指定画几行几列,我们设置 1 行 5 列和 2 行 4 列:

# 1 行 5 列
p1 <- p + facet_wrap(~cut,nrow = 1,ncol = 5)
# 2 行 4 列
p2 <- p + facet_wrap(~cut,nrow = 2,ncol = 4)

p1 + p2

scales 参数有 4 种可选,分别是 fixedfreefree_xfree_y,默认是第一种,分面后的图形坐标系都保持一样。

free表示分面后的图形的 x 和 y 轴根据自己数据大小自动调整。

free_x表示分面后的图形的 x 轴自动调整,y 轴所有封面保持一致。

free_y表示分面后的图形的 y 轴自动调整,x 轴所有封面保持一致

p <- ggplot(data = diamonds,aes(x = carat,y = x)) +
  geom_point(aes(color = cut),size = 2,alpha = .75) +
  theme_prism(base_size = 14,border = T) +
  theme_bw()

p + facet_wrap(~cut,scales = 'free')
p1 <- p + facet_wrap(~cut,scales = 'free_x')
p2 <- p + facet_wrap(~cut,scales = 'free_y')

p1 + p2

as.table 参考文档写的是 TRUE 是把最大值的图放在右下角,FALSE 则把最大值的图放在右上角,有点像排序的顺序感觉,看图理解一下:

p1 <- p + facet_wrap(~cut,as.table = T)
p2 <- p + facet_wrap(~cut,as.table = F)

p1 + p2

switch 参数选项有 xyboth 三个,为调整分面标签的位置,x 表示标签在下面,y 表示标签在左边,both 效果和 y 一样:

p + facet_wrap(~cut,switch = 'x')
p + facet_wrap(~cut,switch = 'y')
p + facet_wrap(~cut,switch = 'both')

dir 参数控制图的展示方向,v 为按竖直水平顺序展示,h 表示按水平方向顺序展示,默认水平顺序:

p1 <- p + facet_wrap(~cut)
p2 <- p + facet_wrap(~cut,dir = 'v')
p3 <- p + facet_wrap(~cut,dir = 'h')

p1 / p2 / p3

strip.position 参数和 switch 参数一样,现在用的是这个,用 swich 参数会有 warning 信息,strip.position = c("top", "bottom", "left", "right"),四个选项:

p1 <- p + facet_wrap(~cut,strip.position = 'top')
p2 <- p + facet_wrap(~cut,strip.position = 'bottom')

p1 / p2
p3 <- p + facet_wrap(~cut,strip.position = 'left')
p4 <- p + facet_wrap(~cut,strip.position = 'right')

p3 + p4

此外还可以对多个变量进行分类,不过这种表现方式没有 facet_grid 好:

p + facet_wrap(cut~color~clarity)

2、facet_grid


查看参数:

Usage
facet_grid(
  rows = NULL,
  cols = NULL,
  scales = "fixed",
  space = "fixed",
  shrink = TRUE,
  labeller = "label_value",
  as.table = TRUE,
  switch = NULL,
  drop = TRUE,
  margins = FALSE,
  facets = NULL
)

可以看到参数基本是一样的,多了 spacemargins 参数。我们看看 facet_grid 画图的效果。

分类变量在前 ,表示按行画图:

p + facet_grid(clarity~.)

分类变量在后 ,表示按列画图:

p + facet_grid(~clarity)

按行是 cut 分类、列是 color 分面绘图:

p + facet_grid(cut~color)

space 参数调整每个封面图的坐标轴长度是否按数值适应,参数选项与 scales 一样:

x 和 y 轴都自适应数值大小:

p + facet_grid(color~cut,scales = 'free',space = 'free')

x 轴自适应大小:

p + facet_grid(color~cut,scales = 'free_x',space = 'free_x')

y 轴自适应大小:

p + facet_grid(color~cut,scales = 'free_y',space = 'free_y')

margins 参数会在原来封面图最后多加一列该分面变量的所有数据的汇总列分面,可以是 TUREFALSE,也可以是分类变量,默认是不加的:

p + facet_grid(color~cut,margins = T)

加上 cut 分类变量的汇总数据的分面:

p + facet_grid(color~cut,margins = 'cut')

加上 cutcolor 的,结果和 margins = T 是一样的:

p + facet_grid(color~cut,margins = c('cut','color'))

每个变量还可加上其它变量一起,只需要加个 + 符号即可,有点像 facet_grid 上加了 facet_wrap 功能一样。

cut 加上 clarity 变量在列上:

p + facet_grid(color ~ cut + clarity)

3、分面主题优化


分面主题的调整在 theme 主题里,接下来我们具体介绍。

分面标签背景 可以用 strip.backgroundstrip.background.xstrip.background.y 调整:

一起调整:

p + facet_grid(color~cut) +
  theme(strip.background = element_rect(fill = 'white',
                                        color = 'orange'))

分开调整:

p + facet_grid(color~cut) +
  theme(strip.background.x = element_rect(fill = 'green',
                                        color = 'red'),
        strip.background.y = element_rect(fill = 'orange',
                                          color = 'blue'))

分面矩形与分面图形的距离strip.placementinsideoutside 两个选项。

inside 表示与图形相接:

p + facet_grid(color~cut) +
  theme(strip.placement = 'inside')

outside 表示与图形有一定间隔:

p + facet_grid(color~cut) +
  theme(strip.placement = 'outside')

分面标签字体 可以用 strip.textstrip.text.xstrip.text.y 来控制。

一起控制:

p + facet_grid(color~cut) +
  theme(strip.text = element_text(color = 'red',size = 10,face = 'bold'))

分别调整:

p + facet_grid(color~cut) +
  theme(strip.text.x = element_text(color = 'green',size = 8,face = 'bold'),
        strip.text.y = element_text(color = 'yellow',size = 12,face = 'italic'))

strip.switch.pad.gridstrip.switch.pad.wrap 控制分面矩形与坐标轴的距离,只有当 strip.placement 设置为 outside 时才有效:

p + facet_grid(color~cut) +
  theme(strip.placement = 'outside',
        strip.switch.pad.grid = unit(10,'mm'),
        )

每个分面图间的距离 通过 panel.spacingpanel.spacing.xpanel.spacing.y 控制。

一起调整:

p + facet_grid(color~cut) +
  theme(panel.spacing = unit(5,'mm'))
p + facet_grid(color~cut) +
  theme(panel.spacing = unit(0,'mm'))

分别调整:

p + facet_grid(color~cut) +
  theme(panel.spacing.x = unit(0,'mm'),
        panel.spacing.y = unit(2.5,'mm'))
p + facet_grid(color~cut) +
  theme(panel.spacing.x = unit(2.5,'mm'),
        panel.spacing.y = unit(0,'mm'))



此外我还发现 theme_bw 主题加上 theme_prism 主题加在一起画出来的分面效果还是不错的:

p + facet_grid(color~cut) +
  theme_bw() +
  theme_prism(border = T)


所以今天你学习了吗?



发现更多精彩

关注公众号

欢迎小伙伴留言评论!

今天的分享就到这里了,敬请期待下一篇!

最后欢迎大家分享转发,您的点赞是对我的鼓励肯定

如果觉得对您帮助很大,赏杯快乐水喝喝吧!

推 荐 阅 读




您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存