使用ggplot2制作并列图表

445

我想使用ggplot2包将两个图并排放置,即相当于执行par(mfrow=c(1,2))命令。

例如,我希望以下两个图像能够并排显示,并具有相同的比例。

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

我需要把它们放在同一个数据框中吗?

qplot(displ, hwy, data=mpg, facets = . ~ year) + geom_smooth()

我觉得你也许可以用lattice来做这个。ggplot2是严格要求吗? - JD Long
8
不行。但是我已经花时间调整了qplots,让它变成我喜欢的样子。 :-) 我还在尝试使用ggplot进行实验。 - Christopher DuBois
1
请查看https://dev59.com/Z1wZ5IYBdhLWcg3wJ9Yp。 - Boern
1
有关详细信息,请参阅 egg 包 的文档:在页面上布置多个图形 - Henrik
对于任何超出最基本绘图的需求,您应该使用ggplot而不是qplot。 - Dan Tarr
14个回答

3

还可以考虑使用ggpubr包中的ggarrange函数。它有很多好处,包括在绘图之间对齐坐标轴和将常见的图例合并成一个。


1
根据我的经验,如果您正在尝试在循环中生成图形,gridExtra:grid.arrange非常完美。

简短的代码片段:

gridExtra::grid.arrange(plot1, plot2, ncol = 2)

** 更新此评论以展示如何在for循环中使用grid.arrange()来为分类变量的不同因素生成图表。

for (bin_i in levels(athlete_clean$BMI_cat)) {

plot_BMI <- athlete_clean %>% filter(BMI_cat == bin_i) %>% group_by(BMI_cat,Team) %>% summarize(count_BMI_team = n()) %>% 
          mutate(percentage_cbmiT = round(count_BMI_team/sum(count_BMI_team) * 100,2)) %>% 
          arrange(-count_BMI_team) %>% top_n(10,count_BMI_team) %>% 
          ggplot(aes(x = reorder(Team,count_BMI_team), y = count_BMI_team, fill = Team)) +
            geom_bar(stat = "identity") +
            theme_bw() +
            # facet_wrap(~Medal) +
            labs(title = paste("Top 10 Participating Teams with \n",bin_i," BMI",sep=""), y = "Number of Athletes", 
                 x = paste("Teams - ",bin_i," BMI Category", sep="")) +
            geom_text(aes(label = paste(percentage_cbmiT,"%",sep = "")), 
                      size = 3, check_overlap = T,  position = position_stack(vjust = 0.7) ) +
            theme(axis.text.x = element_text(angle = 00, vjust = 0.5), plot.title = element_text(hjust = 0.5), legend.position = "none") +
            coord_flip()

plot_BMI_Medal <- athlete_clean %>% 
          filter(!is.na(Medal), BMI_cat == bin_i) %>% 
          group_by(BMI_cat,Team) %>% 
          summarize(count_BMI_team = n()) %>% 
          mutate(percentage_cbmiT = round(count_BMI_team/sum(count_BMI_team) * 100,2)) %>% 
          arrange(-count_BMI_team) %>% top_n(10,count_BMI_team) %>% 
          ggplot(aes(x = reorder(Team,count_BMI_team), y = count_BMI_team, fill = Team)) +
            geom_bar(stat = "identity") +
            theme_bw() +
            # facet_wrap(~Medal) +
            labs(title = paste("Top 10 Winning Teams with \n",bin_i," BMI",sep=""), y = "Number of Athletes", 
                 x = paste("Teams - ",bin_i," BMI Category", sep="")) +
            geom_text(aes(label = paste(percentage_cbmiT,"%",sep = "")), 
                      size = 3, check_overlap = T,  position = position_stack(vjust = 0.7) ) +
            theme(axis.text.x = element_text(angle = 00, vjust = 0.5), plot.title = element_text(hjust = 0.5), legend.position = "none") +
            coord_flip()

gridExtra::grid.arrange(plot_BMI, plot_BMI_Medal, ncol = 2)

}

从上面的循环中,以下是一个示例图。上述循环将为所有BMI类别级别生成多个图。 示例图片 如果您希望在for循环中看到更全面地使用grid.arrange(),请查看https://rpubs.com/Mayank7j_2020/olympic_data_2000_2016

你的回答如何改进Baptiste在2017年12月2日4:20的回答?你的回答似乎是重复的。请查看这里有关可接受答案的内容。[答案] - Peter
我无法在循环内按需要分割图表,因此寻求建议。 最初,我编写了完整的for循环代码段以及其实现,但暂时决定不使用。将在一周左右更新完整的代码。 - Mayank Agrawal
我最初尝试使用cowplot包来完成它,但是没有成功。 在我的快速扫描中,没有人提到在for循环内部使用多个绘图解决方案,因此我发表了评论。如果我错了,请引用任何评论。 - Mayank Agrawal
1
如果你的答案中包含了一个for循环,那就会有所不同。 - Peter
我可能会在这里更新一周,然后将整个项目上传到Kaggle。 谢谢。 - Mayank Agrawal
显示剩余2条评论

1
上述解决方案可能不太高效,如果您想使用循环绘制多个ggplot图(例如:使用循环创建具有不同Y轴值的多个ggplot图),这是分析未知(或大型)数据集的必要步骤(例如,当您想要绘制数据集中所有变量的计数时)。
下面的代码展示了如何使用上述提到的“multiplot()”来实现这一点,其源代码在此处:http://www.cookbook-r.com/Graphs/Multiple_graphs_on_one_page_(ggplot2):
plotAllCounts <- function (dt){   
  plots <- list();
  for(i in 1:ncol(dt)) {
    strX = names(dt)[i]
    print(sprintf("%i: strX = %s", i, strX))
    plots[[i]] <- ggplot(dt) + xlab(strX) +
      geom_point(aes_string(strX),stat="count")
  }

  columnsToPlot <- floor(sqrt(ncol(dt)))
  multiplot(plotlist = plots, cols = columnsToPlot)
}

现在运行该函数-使用ggplot在一页上打印所有变量的计数
dt = ggplot2::diamonds
plotAllCounts(dt)

需要注意的一件事是:
在使用ggplot时,通常会在循环中使用aes(get(strX)),但在上面的代码中,使用aes_string(strX)代替aes(get(strX))将不会绘制所需的图表。相反,它将绘制许多次最后一个图表。我还没有弄清原因——可能与aesaes_stringggplot中的调用有关。

否则,希望您会发现此函数有用。


1
请注意,您的代码在for-loop中生成plots对象,这是在R中高度低效且不推荐的。请参阅以下优秀文章以找到更好的方法:Efficient accumulation in RApplying a function over rows of a data frameRow-oriented workflows in R with the tidyverse - Tung
更高效的遍历变量的方法是使用“整洁评估”方法,该方法自 ggplot2 v.3.0.0 版本以来已经可用。https://dev59.com/Bm445IYBdhLWcg3wcZ8N#52045613 - Tung

-2

cowplot 包提供了一种适合出版的方式,让你以一种不错的方式完成这个任务。

x <- rnorm(100)
eps <- rnorm(100,0,.2)
A = qplot(x,3*x+eps, geom = c("point", "smooth"))+theme_gray()
B = qplot(x,2*x+eps, geom = c("point", "smooth"))+theme_gray()
cowplot::plot_grid(A, B, labels = c("A", "B"), align = "v")

enter image description here


3
请参考包的作者在上面提供的更详细的答案和理由。链接为 https://dev59.com/w3M_5IYBdhLWcg3wvV1w#31223588。 - David LeBauer

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