rggplot2lapply

lapply a ggplot function on multiple inputs with consistent groups


working with the following data structure:

group <- c(rep(1, 30), rep(2, 30))
animal <- c(rep(c(rep(1, 6), rep(2, 6), rep(3, 6), rep(4, 6), rep(5, 6)), 2))
velocity <- c(rpois(60, 7))
second <- rep(c(1:6), 10)
bdf <- data.frame(group, animal, velocity, second)

I have a ggplot function that I wrote to plot velocity for each animal and apply across the group variable. It works like such:

plotvelocity <- function(n) {
  ggplot(n)+
    geom_path(mapping=aes(x=second, y=velocity, group=group))+
    theme_classic()+
    facet_wrap(~animal, ncol=1)
}
behaviorlist <- split(bdf, bdf$group)
plotvelocitylist <- lapply(behaviorlist, plotvelocity)

However, I'd really like to visualize the 97th percentile for velocity on each group. I've written the following:

bdf_quantiles <- bdf %>%
  group_by(group) %>%
  summarize(quantile = quantile(velocity, probs=c(0.97)))

plotvelocity <- function(n, q) {
  ggplot(n)+
    geom_path(mapping=aes(x=second, y=velocity, group=group))+
    theme_classic()+
    geom_hline(q, mapping=aes(yintercept=quantile))+
    facet_wrap(~animal, ncol=1)
}
behaviorlist <- split(bdf, bdf$group)
plotvelocitylist <- lapply(behaviorlist, plotvelocity, bdf_quantiles)

But it plots all of the quantiles of the bdf_quantiles df, instead of matching each percentile to the corresponding group. I've tried using mapply as specified here, but for some reason ggplot is not cooperating with the matrix format. Also, I have played around with using +stat_sum() instead of +hline(), but importantly, I'd like to visualize the percentile of the group variable, not each individual animal facet. I'm not sure if stat_sum() would do that, but I haven't had any luck with it. Any help would be appreciated. Thanks.


Solution

  • You either have to subset the list of quantiles that you are passing into the function to match the current group

    plotvelocity <- function(n, q) {
      qq <- filter(q, group==first(pull(n, group)))
      ggplot(n)+
        geom_path(mapping=aes(x=second, y=velocity, group=group))+
        theme_classic()+
        geom_hline(qq, mapping=aes(yintercept=quantile))+
        facet_wrap(~animal, ncol=1)
    }
    

    or just calculate the quantile in the function itself

    plotvelocity <- function(n) {
      q <- n %>% summarize(quantile = quantile(velocity, probs=c(0.97)))
      ggplot(n)+
        geom_path(mapping=aes(x=second, y=velocity, group=group))+
        theme_classic()+
        geom_hline(q, mapping=aes(yintercept=quantile))+
        facet_wrap(~animal, ncol=1)
    }
    plotvelocitylist <- lapply(behaviorlist, plotvelocity)