alchimj
alchimj

Reputation: 1

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!!

Upvotes: 0

Views: 459

Answers (2)

alchimj
alchimj

Reputation: 1

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!

Upvotes: 0

yutannihilation
yutannihilation

Reputation: 808

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)

Upvotes: 1

Related Questions