R作图 ggplot2图片的布局排版

ggplot2是R语言中用来可视化的利器,其图层逻辑非常人性化,简单的说就是一句话一张图,后一张图叠加在前一张图上,所想表达的几乎都可以用一句代码在图形上展示出来。如果刚开始接触R作图的话,完全可以快速地从ggplot2入门而不用去管base作图,ggplot2的用法已经完全覆盖base作图,除了一项(我至今接触到的)——图片布局

刚开始我也曾困惑过,base作图有par()函数来对多张图片进行布局排布,但该函数对于ggplot2的作图结果则是完全无效的。然后网上搜了一通,找了个grid包,其可以说专门用来排版图片的,当然也支持ggplot2,但是个人感觉使用起来不太顺手(由于其功能有点复杂了)。最近刚看到一个函数multiplot,查了下是来自Rmisc包,这个包发布于2013年,我在这之前也没用过,但是这个函数对于ggplot2结果图片的排布来说简单好使(后来简单看了下multiplot函数的源码,原来其就是用了grid包来实现布局的。。。相当于将grid包中关键的部分又封装了下),下面记录下上述两种方法:

先找一个测试集数据,查了下R自带的数据集,最后选用airquality数据集,其记录了纽约1973年5-9月份每日空气质量,如测量对象有OzoneSolar.RWindTemp

data <- airquality
names(data)
#[1] "Ozone"   "Solar.R" "Wind"    "Temp"    "Month"   "Day"

我想用箱线图展示每个月份下上述4个测量值的变化,那么可以用代码一张一张分别作图,也可以用lapply函数进行循环作图,为了代码的整洁肯定选用后者

vars <- names(data)[1:4]
p <- lapply(vars, function(x){
  ggplot(data, aes(x = Month, y = eval(parse(text = x)), fill = Month)) +
    geom_boxplot(na.rm = T) +
    labs(y = x, title = paste0(x, " In Different Months")) +
    theme_light() +
    theme(plot.title = element_text(hjust = 0.5)) +
    guides(fill = "none")
})

这里有个小技巧,通常如果将function(x)中的x(x这里的类型是字符串)直接作为ggplot2的y变量的值是不行的,需要对x做个转化,这里就用了parseeval函数,前者将x类型转化为表达式(但不求解),后者则是对表达式求解,我也是长见识了

p为列表,p[[1]]代表第一张图

  1. 用Rmisc包的multiplot函数

    首先用最简单的方法做两张图

    multiplot(plotlist = p[1:4], cols = 2)      
    

    rmisc_boxplot1

    multiplot(plotlist = p[1:3], cols = 3)
    

    rmisc_boxplot2

    这里col表示每列的图片数目

    我们还可以通过layout参数来设定图片的排布矩阵,如:

    multiplot(plotlist = p[1:3], layout = matrix(c(1,2,3,3), nrow = 2))
    

    rmisc_boxplot3

    multiplot(plotlist = p[1:3], layout = matrix(c(1,2,3,3), nrow = 2, byrow = T))
    

    rmisc_boxplot4

    是不是很方便。。。。

  2. 用grid包的viewport函数

    grib包的viewport函数可以画上面的所有布局的图(PS.multiplot函数本来就是调用grib包的,所以当然都可以画出来),但是有一种形式是multiplot函数无法比较方便的实现,但viewport函数可以(主要还是multiplot函数没封装完全,我看了下,重新改下函数,还是可以实现的),如下

    先pushViewport设定一个空白画布,然后用pushViewport函数布局(主要用来设定后续viewport的可放置的位置)

    library(grid)
    grid.newpage()
    pushViewport(viewport(layout = grid.layout(3,4)))
    

    然后用print输出图片

    print(p[[1]], vp = viewport(layout.pos.row = 1:3, layout.pos.col = 1))
    print(p[[2]], vp = viewport(layout.pos.row = 1, layout.pos.col = 2:3))
    print(p[[3]], vp = viewport(layout.pos.row = 3, layout.pos.col = 2:3))
    print(p[[4]], vp = viewport(layout.pos.row = 1:3, layout.pos.col = 4))
    

    grib_boxplot1

    如果上述图片要用multiplot函数来实现,则需要这样写,PS.这矩阵写的好绕,还是viewport显得简洁了

    multiplot(plotlist = p[1:4], layout = matrix(c(1,2,2,4,1,0,0,4,1,3,3,4), nrow = 3, byrow = T))
    

参考资料:

R统计绘图(2):grid布局
扎心实战案例:麻(shi)雀(zhan)虽小,五脏俱全

本文出自于http://www.bioinfo-scrounger.com转载请注明出处