使用ggplot2在一个画布中绘制多个图表

32
我试图基于这个表格将两个ggplot2图合并成一个:
   Type    RatingA  RatingB
1  One     3        36
2  Two     5        53
3  One     5        57
4  One     7        74
5  Three   4        38
6  Three   8        83

我想制作两个散点图,y轴上显示评分的平均值,x轴上显示类型。

这是我创建每个图表的方式:

p1 <- ggplot(test, aes(x=reorder(Type, RatingA, mean), y=RatingA)) +
        stat_summary(fun.y="mean", geom="point")

p2 <- ggplot(test, aes(x=reorder(Type, RatingB, mean), y=RatingB)) + 
        stat_summary(fun.y="mean", geom="point")

由于p1和p2具有相同的x轴,我希望它们垂直排序。我查看了facet_align,但找不到能完成此任务的内容。


类似问题:https://dev59.com/w3M_5IYBdhLWcg3wvV1w - Mikko
请参考此链接,其中提供了多种实现方法(2018年9月)。 - Tung
4个回答

49

你可以使用 gridExtra 包中的 grid.arrange() 函数,如下所示:

grid.arrange(p1, p2)

2
你能添加更多信息吗?那个函数是从哪里来的?如何导入它?此外,看起来该函数并没有将图绘制到同一个画布上,而是将两个图拼接在一起。 - Soren
1
@Sören grid.arrange在gridExtra包中,就像我之前说的那样。您可以像导入其他任何包一样导入它。 - Ista

15

Julio,

你提到p1和p2有相同的x轴,但是你基于均值进行的重新排序并不能使它们相同。p1的轴为“one-->two-->three”,而p2的轴为“two-->one-->three”。这是有意为之吗?

无论如何,ggplot提供了几种其他的解决方案来将这些图表合并成一个,即colourfaceting(你可能已经尝试过了?)。首先要做的是将数据框转换为长格式,可以使用melt函数。我们会将变量"Type"识别为id变量,并且melt函数会将其余的列变量进行融合。

test.m <- melt(test, id.var = "Type")

快速检查新对象的结构表明,除了type的级别有些错乱之外,大部分都符合要求:

> str(test.m)
'data.frame':   12 obs. of  3 variables:
 $ Type    : Factor w/ 3 levels "One","Three",..: 1 3 1 1 2 2 1 3 1 1 ...
 $ variable: Factor w/ 2 levels "RatingA","RatingB": 1 1 1 1 1 1 2 2 2 2 ...
 $ value   : int  3 5 5 7 4 8 36 53 57 74 ...

那么让我们重新排列这些级别:

test.m$Type <- factor(test.m$Type, c("One", "Three", "Two"), c("One", "Two", "Three"))
现在是绘图时间。加上颜色:
ggplot(test.m, aes(x = Type, y = value, group = variable, colour = variable)) + 
stat_summary(fun.y = "mean", geom = "point") 
或者使用facets:
ggplot(test.m, aes(x = Type, y = value, group = variable)) + 
stat_summary(fun.y = "mean", geom = "point") +
facet_grid(variable ~ ., scales = "free")

请注意,我在分面时使用了scales = "free"参数,这样每个图都有自己的比例尺。如果您不需要这种效果,请删除该参数。


1
这是针对这个特定问题的更好解决方案,但在一般情况下(例如当两个图形类型不同时),Ista的解决方案更好。 - naught101

10

这是一个旧问题,但我最近发现了 multiplot 函数,它能很好地完成工作。

来自R食谱:multiplot 函数:

该函数本身为:

# Multiple plot function
#
# ggplot objects can be passed in ..., or to plotlist (as a list of ggplot objects)
# - cols:   Number of columns in layout
# - layout: A matrix specifying the layout. If present, 'cols' is ignored.
#
# If the layout is something like matrix(c(1,2,3,3), nrow=2, byrow=TRUE),
# then plot 1 will go in the upper left, 2 will go in the upper right, and
# 3 will go all the way across the bottom.
#
multiplot <- function(..., plotlist=NULL, file, cols=1, layout=NULL) {
  require(grid)

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

  numPlots = length(plots)

  # If layout is NULL, then use 'cols' to determine layout
  if (is.null(layout)) {
    # Make the panel
    # ncol: Number of columns of plots
    # nrow: Number of rows needed, calculated from # of cols
    layout <- matrix(seq(1, cols * ceiling(numPlots/cols)),
                    ncol = cols, nrow = ceiling(numPlots/cols))
  }

 if (numPlots==1) {
    print(plots[[1]])

  } else {
    # Set up the page
    grid.newpage()
    pushViewport(viewport(layout = grid.layout(nrow(layout), ncol(layout))))

    # Make each plot, in the correct location
    for (i in 1:numPlots) {
      # Get the i,j matrix positions of the regions that contain this subplot
      matchidx <- as.data.frame(which(layout == i, arr.ind = TRUE))

      print(plots[[i]], vp = viewport(layout.pos.row = matchidx$row,
                                      layout.pos.col = matchidx$col))
    }
  }
}

你只需将此函数源代码添加至你的脚本中即可。

1
我在这里评论,因为我无法在您提供的链接页面上发表评论...为什么有一个“文件”参数?显然,在该函数中未使用它。 - Stingery
1
@Stingery,好问题。但是我不知道答案。抱歉。 - AndriusZ

0

请看一下 patchwork 包,它允许您通过将多个图表相加来组合它们:

library(patchwork)
p1+p2

为了让它们堆叠在一起,你有两个选项:
p1+p2+plot_layout(ncol=1)

或者:

p1/p2

这个包的文档真的很棒,链接在这里:https://patchwork.data-imaginist.com/index.html

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接