多页,每页有几个 ggplot2 图表和表格,来自多个数据框,每个页面都是一个共同因素的水平
Multiple pages, with several ggplot2 graphs and tables per page, coming from several data frames, each page being the level of a common factor
我有不同的数据框提供相同因素相同水平的信息。
最终我想要一个 pdf,其中包含每个页面的 ggplot2 图、一个 gridExtra tableGrob 和文本作为标题,来自不同的数据框。每个页面将显示 1 个因素水平的信息。
使用 cowplot 我设法很好地组织了 1 页,但我找不到制作 for 循环或其他任何自动执行 ~1000 页的方法。
这是我的数据的可重现示例:
# Loading necessary packages
library(dplyr)
library(ggplot2)
library(grid)
library(gridExtra)
library(gtable)
library(cowplot)
# Creating first data frame df1
fact <- c("level1", "level1", "level1", "level1", "level1", "level1", "level2", "level2", "level2", "level2", "level2", "level2")
fact <- as.factor(fact)
x1 <- c("1A", "1A", "1A", "1B", "1B", "1B", "1A", "1A", "1A", "1B", "1B", "1B")
x2 <- c(0, 1, 5, 0, 1, 5, 0, 1, 5, 0, 1, 5)
x3 <- c(5, 2, 4, 5, 6, 3, 2, 5, 6, 4, 6, 8)
df1 <- cbind.data.frame(fact, x1, x2, x3)
# Creating second data frame df2
fact <- c("level1", "level1", "level2", "level2")
fact <- as.factor(fact)
x4 <- c("1A", "1B", "1A", "1B")
x5 <- c("good", "bad", "good", "good")
df2 <- cbind.data.frame(fact, x4, x5)
# filtering the data frames to keep 1 level of factor fact
i <- "level1"
df1_plot <- df1 %>% filter(fact == i)
df2_table <- df2 %>% filter(fact == i)
# defining ggplot graphs and gridExtra table
plot1 <- ggplot(data = df1_plot, aes(x = x2, y = x3, color = x1)) + geom_line()
plot2 <- ggplot(data = df1_plot, aes(x = x2, y = x3, color = x1)) + geom_point()
table1 <- tableGrob(df2_table, theme = ttheme_minimal(), rows = NULL)
# Plotting everything in place and adding the level (i) as title of the page
pdf(file = sprintf("%s.pdf", i), width = 9, height = 12, onefile = TRUE)
table_drawn <- ggdraw() + draw_grob(table1)
right_column <- plot_grid(table_drawn, plot1, labels = c("B", "C"), ncol = 1, rel_heights = c(1, 3), scale = 0.9)
bottom_row <- plot_grid(plot2, right_column, labels = c("A", ""), nrow = 1, rel_widths = c(1.5, 2))
title1 <- ggdraw() + draw_label(i, fontface='bold', x = 0, y = 0.5, hjust = 0, vjust = 1, size = 14)
upper_row <- plot_grid(title1, hjust = 0, ncol = 1)
plot_grid(upper_row, bottom_row, ncol=1, rel_heights=c(0.1, 1))
dev.off()
这个最小示例的结果很丑陋,对此我深表歉意!
在我的真实数据中,它达到了 "publication figure quality",这对于 cowplot 来说非常棒。
所以理想情况下,我能够做到这一点,因为我轮流考虑因子 "fact" 的所有水平(这里是 2 个水平,在真实数据中 ~ 1000)...这就是我的地方(非常有限)R 知识和已回答问题的互联网探索结束。
我应该使用 for 循环,制作列表,列表列表,使用 dplyr group_by?
非常感谢任何帮助!
这是一个更简单的方法。首先,我们将两个数据帧绑定到一个数据帧中。然后在 lapply
内,我们将数据框按 fact
拆分,并连续为 fact
的每个级别创建整个布局:
dat = bind_rows(df1, df2 %>% rename(x1=x4), .id="df")
lapply(split(dat, dat$fact), function(d) {
pdf(paste0(unique(d$fact),".pdf"),9,12)
p = ggplot(d %>% filter(df==1), aes(x2, x3, colour=x1))
grid.draw(plot_grid(p + geom_point(),
plot_grid(tableGrob(d %>% filter(df==2) %>% select(fact,x1,x5),
theme=ttheme_minimal(), rows=NULL),
p + geom_line(),
ncol=1, rel_heights=c(0.1,1)),
ncol=2))
dev.off()
})
除了 lapply
,您还可以使用 purrr
包中的 map
:
library(purrr)
split(dat, dat$fact) %>% map(function(d) {
[...same as above...]
})
下面是两个图表中的第一个:
我有不同的数据框提供相同因素相同水平的信息。 最终我想要一个 pdf,其中包含每个页面的 ggplot2 图、一个 gridExtra tableGrob 和文本作为标题,来自不同的数据框。每个页面将显示 1 个因素水平的信息。 使用 cowplot 我设法很好地组织了 1 页,但我找不到制作 for 循环或其他任何自动执行 ~1000 页的方法。
这是我的数据的可重现示例:
# Loading necessary packages
library(dplyr)
library(ggplot2)
library(grid)
library(gridExtra)
library(gtable)
library(cowplot)
# Creating first data frame df1
fact <- c("level1", "level1", "level1", "level1", "level1", "level1", "level2", "level2", "level2", "level2", "level2", "level2")
fact <- as.factor(fact)
x1 <- c("1A", "1A", "1A", "1B", "1B", "1B", "1A", "1A", "1A", "1B", "1B", "1B")
x2 <- c(0, 1, 5, 0, 1, 5, 0, 1, 5, 0, 1, 5)
x3 <- c(5, 2, 4, 5, 6, 3, 2, 5, 6, 4, 6, 8)
df1 <- cbind.data.frame(fact, x1, x2, x3)
# Creating second data frame df2
fact <- c("level1", "level1", "level2", "level2")
fact <- as.factor(fact)
x4 <- c("1A", "1B", "1A", "1B")
x5 <- c("good", "bad", "good", "good")
df2 <- cbind.data.frame(fact, x4, x5)
# filtering the data frames to keep 1 level of factor fact
i <- "level1"
df1_plot <- df1 %>% filter(fact == i)
df2_table <- df2 %>% filter(fact == i)
# defining ggplot graphs and gridExtra table
plot1 <- ggplot(data = df1_plot, aes(x = x2, y = x3, color = x1)) + geom_line()
plot2 <- ggplot(data = df1_plot, aes(x = x2, y = x3, color = x1)) + geom_point()
table1 <- tableGrob(df2_table, theme = ttheme_minimal(), rows = NULL)
# Plotting everything in place and adding the level (i) as title of the page
pdf(file = sprintf("%s.pdf", i), width = 9, height = 12, onefile = TRUE)
table_drawn <- ggdraw() + draw_grob(table1)
right_column <- plot_grid(table_drawn, plot1, labels = c("B", "C"), ncol = 1, rel_heights = c(1, 3), scale = 0.9)
bottom_row <- plot_grid(plot2, right_column, labels = c("A", ""), nrow = 1, rel_widths = c(1.5, 2))
title1 <- ggdraw() + draw_label(i, fontface='bold', x = 0, y = 0.5, hjust = 0, vjust = 1, size = 14)
upper_row <- plot_grid(title1, hjust = 0, ncol = 1)
plot_grid(upper_row, bottom_row, ncol=1, rel_heights=c(0.1, 1))
dev.off()
这个最小示例的结果很丑陋,对此我深表歉意! 在我的真实数据中,它达到了 "publication figure quality",这对于 cowplot 来说非常棒。
所以理想情况下,我能够做到这一点,因为我轮流考虑因子 "fact" 的所有水平(这里是 2 个水平,在真实数据中 ~ 1000)...这就是我的地方(非常有限)R 知识和已回答问题的互联网探索结束。 我应该使用 for 循环,制作列表,列表列表,使用 dplyr group_by?
非常感谢任何帮助!
这是一个更简单的方法。首先,我们将两个数据帧绑定到一个数据帧中。然后在 lapply
内,我们将数据框按 fact
拆分,并连续为 fact
的每个级别创建整个布局:
dat = bind_rows(df1, df2 %>% rename(x1=x4), .id="df")
lapply(split(dat, dat$fact), function(d) {
pdf(paste0(unique(d$fact),".pdf"),9,12)
p = ggplot(d %>% filter(df==1), aes(x2, x3, colour=x1))
grid.draw(plot_grid(p + geom_point(),
plot_grid(tableGrob(d %>% filter(df==2) %>% select(fact,x1,x5),
theme=ttheme_minimal(), rows=NULL),
p + geom_line(),
ncol=1, rel_heights=c(0.1,1)),
ncol=2))
dev.off()
})
除了 lapply
,您还可以使用 purrr
包中的 map
:
library(purrr)
split(dat, dat$fact) %>% map(function(d) {
[...same as above...]
})
下面是两个图表中的第一个: