2017-01-27 39 views
2

У меня разные кадры данных, содержащие информацию о тех же уровнях одного и того же коэффициента. В конце концов я хотел бы иметь pdf-файл, содержащий для каждой страницы графики ggplot2, gridExtra tableGrob и текст как заголовок, поступающий из разных фреймов данных. На каждой странице будет отображаться информация для 1 уровня фактора. Использование cowplot Мне удалось упорядочить 1 страницу красиво, но я не мог найти способ сделать цикл for или что-нибудь еще, что делает 1000 страниц автоматически.Несколько страниц, с несколькими графиками ggplot2 и таблицами на странице, поступающими из нескольких кадров данных, причем каждая страница является уровнем общего коэффициента

Вот воспроизводимый пример моих данных:

# 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() 

В результате этого минимального примера некрасиво, я извиняюсь за это! В моих реальных данных он достигает «качества фигуры публикации», который так замечателен с коверной плащкой.

В идеале я бы смог сделать это для того, чтобы я принимал по очереди все уровни фактора «факт» (здесь 2 уровня, в реальных данных ~ 1000) ... Здесь мой (очень ограниченный) Знание R и интернет-исследование уже ответивших вопросов доходят до конца. Должен ли я использовать цикл for, составлять список, список списков, использовать dplyr group_by?

Любая помощь очень ценится!

+0

'Ошибка в sprintf ("% s.pdf ", test): объект 'test' not found' –

+0

Действительно ли ≈ 1000 участков/страниц? В зависимости от варианта использования динамический сюжет с сюжетным или блестящим будет работать легче. – alistaire

+0

вы также можете просто использовать что-то вроде ghostscript для объединения всех отдельных PDF-файлов в соответствии с [этим ответом] (http://stackoverflow.com/a/19358402/5359531) – user5359531

ответ

0

Вот более простой подход. Во-первых, мы привязываем два кадра данных к одному кадру данных. Затем в течение 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, вы можете также использовать map из purrr пакета:

library(purrr) 

split(dat, dat$fact) %>% map(function(d) { 
[...same as above...] 
}) 

Посмотрите, на что похож первый из двух графиков:

enter image description here

+0

Спасибо, это сработало! С дополнительным значением plot_grid для заголовка. –