Search code examples
rggplot2ggpubr

Adding Bracket for ggpubr statistical test comparisons returns "object not found" error


I am trying to create a multifactor plot with statistics and I used the method as described here: Adding bracket for ggpubr statistical test comparisons. However, doing so causes an error of "object 'supp' not found".

library(ggpubr)
data("ToothGrowth")

ToothGrowth$dose <- as.factor(ToothGrowth$dose)
head(ToothGrowth)

p <- ggplot(ToothGrowth,
            aes(
            x = dose,
            y = len,
            fill=supp
            )) +
  geom_boxplot(width=0.8,lwd=0.7, alpha=0.6, outlier.color="black", outlier.size=1) + 
  geom_point(shape=21, aes(fill=supp), size=1, position=position_dodge(width=0.8))

p

compare_means(formula=len~supp, group.by="dose", data=ToothGrowth) %>%
  mutate(dose=factor(dose))

p + geom_bracket(aes(label=p.format, xmin=dose, xmax=dose),
           y.position=max(ToothGrowth$len) * 1.05,
           bracket.shorten=0.4,
           data=compare_means(formula=len~supp, group.by="dose", data=ToothGrowth) %>%
              mutate(dose=factor(dose)))`

The correct plot is made when I plot p, and the compare_means code gives the correct tibble output, but when I do the p+geom_bracket code I get the following error: Error in geom_bracket(): ! Problem while computing aesthetics. ℹ Error occurred in the 3rd layer. Caused by error in FUN()`: ! object 'supp' not found

Backtrace: ▆

  1. ├─base (local) <fn>(x)
  2. ├─ggplot2:::print.ggplot(x)
  3. │ ├─ggplot2::ggplot_build(x)
  4. │ └─ggplot2:::ggplot_build.ggplot(x)
  5. │ └─ggplot2:::by_layer(...)
  6. │ ├─rlang::try_fetch(...)
  7. │ │ ├─base::tryCatch(...)
  8. │ │ │ └─base (local) tryCatchList(expr, classes, parentenv, handlers)
  9. │ │ │ └─base (local) tryCatchOne(expr, names, parentenv, handlers[[1L]])
  10. │ │ │ └─base (local) doTryCatch(return(expr), name, parentenv, handler)
  11. │ │ └─base::withCallingHandlers(...)
  12. │ └─ggplot2 (local) f(l = layers[[i]], d = data[[i]])
  13. │ └─l$compute_aesthetics(d, plot)
  14. │ └─ggplot2 (local) compute_aesthetics(..., self = self)
  15. │ └─base::lapply(aesthetics, eval_tidy, data = data, env = env)
  16. │ └─rlang (local) FUN(X[[i]], ...)
  17. └─base::.handleSimpleError(...)
  18. └─rlang (local) h(simpleError(msg, call))
  19. └─handlers[[1L]](cnd)
    
  20.   └─cli::cli_abort(...)
    
  21.     └─rlang::abort(...)
    

` How should I fix this to get my code to work?


Solution

  • The issue is that you specified fill=supp as a global aesthetic. Hence, it will be applied in each geom layer and ggplot will look for and requires a column with name supp in the data of each geom. This is however not the case in the dataframe returned by compare_means. Hence you get an error. To fix that make fill a local aes for geom_boxplot too as you already have done for geom_point:

    library(ggpubr)
    #> Loading required package: ggplot2
    data("ToothGrowth")
    
    ToothGrowth$dose <- as.factor(ToothGrowth$dose)
    
    p <- ggplot(
      ToothGrowth,
      aes(
        x = dose,
        y = len
      )
    ) +
      geom_boxplot(aes(fill = supp), width = 0.8, lwd = 0.7, alpha = 0.6, outlier.color = "black", outlier.size = 1) +
      geom_point(aes(fill = supp), shape = 21, size = 1, position = position_dodge(width = 0.8))
    
    p + geom_bracket(aes(label = p.format, xmin = dose, xmax = dose),
      y.position = max(ToothGrowth$len) * 1.05,
      bracket.shorten = 0.4,
      data = compare_means(formula = len ~ supp, group.by = "dose", data = ToothGrowth) %>%
        mutate(dose = factor(dose))
    )