与ggplot2并排绘制

Chr*_*ois 315 visualization r ggplot2

我想使用ggplot2包并排放置两个图,即相当于par(mfrow=c(1,2)).

例如,我希望以下两个图表以相同的比例并排显示.

x <- rnorm(100)
eps <- rnorm(100,0,.2)
qplot(x,3*x+eps)
qplot(x,2*x+eps)
Run Code Online (Sandbox Code Playgroud)

我需要将它们放在相同的data.frame中吗?

qplot(displ, hwy, data=mpg, facets = . ~ year) + geom_smooth()
Run Code Online (Sandbox Code Playgroud)

Dav*_*uer 458

任何ggplots并排(或网格上的n个绘图)

该功能grid.arrange()gridExtra包将结合多条曲线; 这就是你如何并排放置两个.

require(gridExtra)
plot1 <- qplot(1)
plot2 <- qplot(1)
grid.arrange(plot1, plot2, ncol=2)
Run Code Online (Sandbox Code Playgroud)

当两个图不是基于相同的数据时,这很有用,例如,如果要在不使用reshape()的情况下绘制不同的变量.

这会将输出绘制为副作用.要打印副作用到文件中,指定一个设备驱动程序(如pdf,png等),例如

pdf("foo.pdf")
grid.arrange(plot1, plot2)
dev.off()
Run Code Online (Sandbox Code Playgroud)

或者,arrangeGrob()与...结合使用ggsave(),

ggsave("foo.pdf", arrangeGrob(plot1, plot2))
Run Code Online (Sandbox Code Playgroud)

这相当于使用两个不同的图par(mfrow = c(1,2)).这不仅节省了安排数据的时间,还需要两个不同的图.


附录:使用Facets

方面有助于为不同的组制作类似的图.这在下面的许多答案中都有所指出,但我想用与上述图相当的例子来强调这种方法.

mydata <- data.frame(myGroup = c('a', 'b'), myX = c(1,1))

qplot(data = mydata, 
    x = myX, 
    facets = ~myGroup)

ggplot(data = mydata) + 
    geom_bar(aes(myX)) + 
    facet_wrap(~myGroup)
Run Code Online (Sandbox Code Playgroud)

更新

这个plot_grid功能cowplot值得一试作为替代grid.arrange.请参阅下面@ claus-wilke 的回答这个小插图的等效方法; 但该功能允许根据此插图对绘图位置和大小进行更精细的控制.

  • 当我使用ggplot对象运行代码时,sidebysideplot为null.如果要将输出保存到文件,请使用gridArrange.见http://stackoverflow.com/questions/17059099/saving-grid-arrange-plot-to-file (2认同)

Cla*_*lke 139

基于这种解决方案的一个缺点grid.arrange是它们很难用大多数期刊所需的字母(A,B等)来标记图.

我编写了cowplot包来解决这个(以及其他一些)问题,特别是函数plot_grid():

library(cowplot)

iris1 <- ggplot(iris, aes(x = Species, y = Sepal.Length)) +
  geom_boxplot() + theme_bw()

iris2 <- ggplot(iris, aes(x = Sepal.Length, fill = Species)) +
  geom_density(alpha = 0.7) + theme_bw() +
  theme(legend.position = c(0.8, 0.8))

plot_grid(iris1, iris2, labels = "AUTO")
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

plot_grid()返回的对象是另一个ggplot2对象,您可以ggsave()像往常一样保存它:

p <- plot_grid(iris1, iris2, labels = "AUTO")
ggsave("plot.pdf", p)
Run Code Online (Sandbox Code Playgroud)

或者,您可以使用cowplot函数save_plot(),这是一个薄的包装ggsave(),可以很容易地获得组合图的正确尺寸,例如:

p <- plot_grid(iris1, iris2, labels = "AUTO")
save_plot("plot.pdf", p, ncol = 2)
Run Code Online (Sandbox Code Playgroud)

(该ncol = 2论证告诉save_plot()我有两个并排的图,save_plot()并使保存的图像宽两倍.)

有关如何在网格中排列绘图的更深入描述,请参阅此插图.还有一个小插图解释如何制作带有共享图例的情节.

一个常见的混淆点是cowplot包改变了默认的ggplot2主题.包的行为方式是因为它最初是为内部实验室使用而编写的,我们从不使用默认主题.如果这会导致问题,您可以使用以下三种方法之一来解决它们:

1.为每个绘图手动设置主题.我认为总是为每个情节指定一个特定的主题是很好的做法,就像我+ theme_bw()在上面的例子中所做的那样.如果指定特定主题,则默认主题无关紧要.

2.将默认主题恢复为ggplot2默认值.您可以使用一行代码执行此操作:

theme_set(theme_gray())
Run Code Online (Sandbox Code Playgroud)

3.在不附加包装的情况下调用cowplot功能.您也不能通过预先调用来调用library(cowplot)require(cowplot)改为调用cowplot函数cowplot::.例如,使用ggplot2默认主题的上述示例将变为:

## Commented out, we don't call this
# library(cowplot)

iris1 <- ggplot(iris, aes(x = Species, y = Sepal.Length)) +
  geom_boxplot()

iris2 <- ggplot(iris, aes(x = Sepal.Length, fill = Species)) +
  geom_density(alpha = 0.7) +
  theme(legend.position = c(0.8, 0.8))

cowplot::plot_grid(iris1, iris2, labels = "AUTO")
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

更新:从ggplot2 3.0.0开始,可以直接标记图,例如参见此处.

  • 这个包牛皮图真的很棒!我认为在那些喜欢使用ggplot2的人中应该更受欢迎.谢谢!只有一个建议,我认为如果可以选择为组合图添加主标题会更好. (9认同)
  • 有没有办法使用“plot_grid()”指定面板大小?我只是尝试使用它,但它压垮了我的身材。也许我需要在使用 `plot_grid()` 之前指定 ggplot 图像大小? (2认同)

Dav*_*uer 47

您可以使用Winston Chang的R cookbook中的以下multiplot功能

multiplot(plot1, plot2, cols=2)
Run Code Online (Sandbox Code Playgroud)
multiplot <- function(..., plotlist=NULL, cols) {
    require(grid)

    # Make a list from the ... arguments and plotlist
    plots <- c(list(...), plotlist)

    numPlots = length(plots)

    # Make the panel
    plotCols = cols                          # Number of columns of plots
    plotRows = ceiling(numPlots/plotCols) # Number of rows needed, calculated from # of cols

    # Set up the page
    grid.newpage()
    pushViewport(viewport(layout = grid.layout(plotRows, plotCols)))
    vplayout <- function(x, y)
        viewport(layout.pos.row = x, layout.pos.col = y)

    # Make each plot, in the correct location
    for (i in 1:numPlots) {
        curRow = ceiling(i/plotCols)
        curCol = (i-1) %% plotCols + 1
        print(plots[[i]], vp = vplayout(curRow, curCol ))
    }

}
Run Code Online (Sandbox Code Playgroud)


Dee*_*ena 19

使用拼凑包,您只需使用+运算符:

# install.packages("devtools")
devtools::install_github("thomasp85/patchwork")

library(ggplot2)
p1 <- ggplot(mtcars) + geom_point(aes(mpg, disp))
p2 <- ggplot(mtcars) + geom_boxplot(aes(gear, disp, group = gear))

library(patchwork)
p1 + p2
Run Code Online (Sandbox Code Playgroud)

拼凑物

  • Patchwork 是对图形布局包景观的一个很棒的补充。谢谢! (2认同)

Dir*_*tel 17

是的,您需要妥善安排数据.一种方法是:

X <- data.frame(x=rep(x,2),
                y=c(3*x+eps, 2*x+eps),
                case=rep(c("first","second"), each=100))

qplot(x, y, data=X, facets = . ~ case) + geom_smooth()
Run Code Online (Sandbox Code Playgroud)

我相信在plyr或重塑方面有更好的技巧 - 我仍然没有真正掌握Hadley所有这些强大的包装.


Thi*_*rry 15

使用reshape包你可以做这样的事情.

library(ggplot2)
wide <- data.frame(x = rnorm(100), eps = rnorm(100, 0, .2))
wide$first <- with(wide, 3 * x + eps)
wide$second <- with(wide, 2 * x + eps)
long <- melt(wide, id.vars = c("x", "eps"))
ggplot(long, aes(x = x, y = value)) + geom_smooth() + geom_point() + facet_grid(.~ variable)
Run Code Online (Sandbox Code Playgroud)


Jer*_*lim 10

更新:这个答案非常陈旧.gridExtra::grid.arrange()现在是推荐的方法.我把它留在这里以防它可能有用.


Stephen Turner Getting Genetics Done博客发布了该arrange()功能(请参阅发布申请说明)

vp.layout <- function(x, y) viewport(layout.pos.row=x, layout.pos.col=y)
arrange <- function(..., nrow=NULL, ncol=NULL, as.table=FALSE) {
 dots <- list(...)
 n <- length(dots)
 if(is.null(nrow) & is.null(ncol)) { nrow = floor(n/2) ; ncol = ceiling(n/nrow)}
 if(is.null(nrow)) { nrow = ceiling(n/ncol)}
 if(is.null(ncol)) { ncol = ceiling(n/nrow)}
        ## NOTE see n2mfrow in grDevices for possible alternative
grid.newpage()
pushViewport(viewport(layout=grid.layout(nrow,ncol) ) )
 ii.p <- 1
 for(ii.row in seq(1, nrow)){
 ii.table.row <- ii.row 
 if(as.table) {ii.table.row <- nrow - ii.table.row + 1}
  for(ii.col in seq(1, ncol)){
   ii.table <- ii.p
   if(ii.p > n) break
   print(dots[[ii.table]], vp=vp.layout(ii.table.row, ii.col))
   ii.p <- ii.p + 1
  }
 }
}
Run Code Online (Sandbox Code Playgroud)

  • 它基本上是一个非常过时的`grid.arrange`版本(希望我当时没有在邮件列表上发布它 - 没有办法更新这些在线资源),如果你问我,打包版本是更好的选择 (9认同)

Tun*_*ung 10

还有值得一提的multipanelfigure程序包。另请参阅此答案

library(ggplot2)
theme_set(theme_bw())

q1 <- ggplot(mtcars) + geom_point(aes(mpg, disp))
q2 <- ggplot(mtcars) + geom_boxplot(aes(gear, disp, group = gear))
q3 <- ggplot(mtcars) + geom_smooth(aes(disp, qsec))
q4 <- ggplot(mtcars) + geom_bar(aes(carb))

library(magrittr)
library(multipanelfigure)
figure1 <- multi_panel_figure(columns = 2, rows = 2, panel_label_type = "none")
# show the layout
figure1
Run Code Online (Sandbox Code Playgroud)

figure1 %<>%
  fill_panel(q1, column = 1, row = 1) %<>%
  fill_panel(q2, column = 2, row = 1) %<>%
  fill_panel(q3, column = 1, row = 2) %<>%
  fill_panel(q4, column = 2, row = 2)
figure1
Run Code Online (Sandbox Code Playgroud)

# complex layout
figure2 <- multi_panel_figure(columns = 3, rows = 3, panel_label_type = "upper-roman")
figure2
Run Code Online (Sandbox Code Playgroud)

figure2 %<>%
  fill_panel(q1, column = 1:2, row = 1) %<>%
  fill_panel(q2, column = 3, row = 1) %<>%
  fill_panel(q3, column = 1, row = 2) %<>%
  fill_panel(q4, column = 2:3, row = 2:3)
figure2
Run Code Online (Sandbox Code Playgroud)

reprex软件包(v0.2.0.9000)创建于2018-07-06 。


bap*_*ste 9

ggplot2基于网格图形,它提供了一个不同的系统,用于在页面上排列图形.该par(mfrow...)命令没有直接等效项,因为网格对象(称为grobs)不一定立即绘制,但可以在转换为图形输出之前作为常规R对象进行存储和操作.这比现在基本图形模型的绘制更具灵活性,但策略必然略有不同.

我写的grid.arrange()是提供尽可能接近的简单界面par(mfrow).在最简单的形式中,代码看起来像:

library(ggplot2)
x <- rnorm(100)
eps <- rnorm(100,0,.2)
p1 <- qplot(x,3*x+eps)
p2 <- qplot(x,2*x+eps)

library(gridExtra)
grid.arrange(p1, p2, ncol = 2)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

此小插图中详细介绍了更多选项.

一个常见的抱怨是情节不一定是对齐的,例如当它们具有不同大小的轴标签时,但这是设计的:grid.arrange不尝试特殊情况ggplot2对象,并将它们平等地对待其他凹凸(例如,格子图) ).它只是将凹凸放置在矩形布局中.

对于ggplot2对象的特殊情况,我编写了另一个函数,ggarrange它具有类似的界面,它尝试对齐绘图面板(包括刻面图)并尝试在用户定义时尊重纵横比.

library(egg)
ggarrange(p1, p2, ncol = 2)
Run Code Online (Sandbox Code Playgroud)

这两个功能兼容ggsave().有关不同选项和一些历史背景的一般概述,此小插图提供了其他信息.


shi*_*iny 5

使用tidyverse

x <- rnorm(100)
eps <- rnorm(100,0,.2)
df <- data.frame(x, eps) %>% 
  mutate(p1 = 3*x+eps, p2 = 2*x+eps) %>% 
  tidyr::gather("plot", "value", 3:4) %>% 
  ggplot(aes(x = x , y = value)) + 
    geom_point() + 
    geom_smooth() + 
    facet_wrap(~plot, ncol =2)

df
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明