简体   繁体   中英

R - ggplot geom_ribbon into apply function multiple plot

I have a problem with my code. I have to print many plots in many pages in pdf and I have solved this with apply function and the grid.Extra package. My last problem (for now) is that I don't understand how it is possible to insert geom_ribbon inside the apply function because the columns are different. I have tried in different ways. Starting from indices and then rebuild the ymin and ymax playing with paste and gsub commands. but this no good idea for resolving this problem. here my code:

plotserieslines <- function(yvar){
  ggplot(d, aes_string(x=d$YEAR, y=yvar,  col = interaction(d$Manage, d$Meteo, sep="|"))) + geom_line( alpha=0.8)+
    geom_ribbon(aes_string(x= d$YEAR, ymin=yvar,ymax=yvar,fill = interaction(d$Manage, d$Meteo, sep="|")), alpha=0.1)+
       theme(legend.key=element_blank(),
          legend.background = element_blank(),
          legend.position = c(0.05, 0.95),
          axis.text=element_text(size=7),
          axis.title=element_text(size=7),
          legend.spacing.y = unit(-2.2, "cm"),
          legend.text=element_text(size=10),
          legend.title=element_blank(),
          legend.key.size = unit(0.7, 'lines')) +
    guides(col = guide_legend(ncol = 1),
           fill=guide_legend( keywidth=0.4,
                              keyheight=0.2,
                              default.unit="cm")) +
    xlab("YEAR") +
    ylab(yvar)
  }
plots <- lapply(names(d[cod]), plotserieslines)

plots1 <-  marrangeGrob(grobs = plots, nrow = 8, ncol = 5)

Thank you very much in advance!!

I think purrr::map2() can do the job.

plotserieslines2 <- function(yvar1, yvar2){
    ggplot(d) +
      geom_line(aes_string(x = "YEAR", y = yvar1, ...), ...) +
      geom_ribbon(aes_string(x = "YEAR", ymax = yvar1, ymin = yvar2, ...), ...) +
      ...
}

cols_ymax <- c("a_max", "b_max", "c_max")
cols_ymin <- c("a_min", "b_min", "c_min")
plots <- map2(cols_ymax, cols_ymin, plotserieslines2)

But, you should consider transforming the original data into "tidy data" form by collapsing the columns into one column per ymax and ymin . Then, instead of lapply() or map() , you can use facet_wrap() like this:


library(tidyr)
library(dplyr, warn.conflicts = FALSE)

d <- data.frame(
  id = 1:3,
  a_max = 1:3 * 10,
  b_max = 1:3 * 11,
  c_max = 1:3 * 12,
  a_min = 1:3 *  3,
  b_min = 1:3 *  4,
  c_min = 1:3 *  5
)

d
#>   id a_max b_max c_max a_min b_min c_min
#> 1  1    10    11    12     3     4     5
#> 2  2    20    22    24     6     8    10
#> 3  3    30    33    36     9    12    15

d_tidy <- d %>%
  gather("type", "value", -id) %>%
  separate(type, into = c("category", "min_or_max"), sep = "_") %>%
  spread(min_or_max, value)

d_tidy
#>   id category max min
#> 1  1        a  10   3
#> 2  1        b  11   4
#> 3  1        c  12   5
#> 4  2        a  20   6
#> 5  2        b  22   8
#> 6  2        c  24  10
#> 7  3        a  30   9
#> 8  3        b  33  12
#> 9  3        c  36  15

library(ggplot2)

ggplot(d_tidy) +
  geom_ribbon(aes(id, ymin = min, ymax = max)) +
  facet_wrap(~ category)

Thank you for your answers!. I have solved this issue using mapply with the option SIMPLIFY=FALSE instead lapply and I have the possibility to use several argument for my function in easy way. With this function I obtain the same list of lapply .

The solution above is very good with facet , but I have hundreds of graphs that I want print in many pdf pages, and I don't know if facet_grid is the properly solution for multipage printing. Anyway, thank you at all.

If there are other useful ways to overcome this problem in smarter ways, write in this post! I have found poor informations about it and many solutions not works properly.

All the best!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM