1

I am using stat_summary to generate a column plot from a dataframe. I would like to report the values to the user via tooltips using geom_col_interactive from ggiraph.

I can get the values from the ggplot using ggplot_build and construct a tooltip as below. However, I cannot work out how to use ggiraph with the plot generated using stat_summary to present tooltips interactively. I could of course use the summary_values tibble and generate a different ggplot using geom_col_interactive, but this would defeat the purpose of using stat_summary (which lends itself nicely to faceting). Is there any way to do this? Or must I use summarySE from Rmisc to generate the tibble to be plotted using geom_col_interactive?

library(tidyverse)

mpg_histogram <- ggplot(mpg, aes(x=as.factor(cyl), fill = as.factor(cyl))) +
  stat_summary(aes(y = hwy), fun = "mean", geom = "bar") +
  stat_summary(aes(y = hwy), fun.data = mean_se,  
               geom = "errorbar", width = 0.2, size = 0.2)

enter image description here

summary_values <- ggplot_build(mpg_histogram)$data[[2]]
summary_values <- summary_values %>%
  mutate(mean = round(y,1), sem = round(ymax-y,1)) %>%
  mutate(tooltip = paste("Mean mpg:",mean,"+/-",sem)) %>%
  select(c(mean,sem,tooltip))
stefan
  • 90,330
  • 6
  • 25
  • 51
dave adelson
  • 853
  • 9
  • 15

2 Answers2

2

One approach to achieve your desired result via stat_summary would be to pass the ggiraph:::GeomInteractiveCol to the geom argument. However, be aware that GeomInteractiveCol is not exported by ggiraph and so requires to use :::. Additionally, to have both the mean and the standard error in the tooltip requires to switch to fun.data="mean_se". For convenience I make use of a simple custom function to create the tooltip:

library(ggplot2)
library(ggiraph)

tooltip <- function(y, ymax, accuracy = .01) {
  mean <- scales::number(y, accuracy = accuracy)
  sem <- scales::number(ymax - y, accuracy = accuracy)
  paste("Mean mpg:", mean, "+/-", sem)
}

gg_point <- ggplot(mpg, aes(x = as.factor(cyl), fill = as.factor(cyl))) +
  stat_summary(aes(y = hwy, tooltip = after_stat(tooltip(y, ymax))),
    fun.data = "mean_se", geom = ggiraph:::GeomInteractiveCol
  ) +
  stat_summary(aes(y = hwy),
    fun.data = mean_se,
    geom = "errorbar", width = 0.2, size = 0.2
  )

girafe(ggobj = gg_point)

enter image description here

stefan
  • 90,330
  • 6
  • 25
  • 51
  • 1
    thank you so much, for both the solution to the problem and for introducing me to after_stat. very elegant. – dave adelson Apr 17 '22 at 16:41
  • ps. given that GeomInteractiveCol is not exported, does this mean that its behavior can't be counted upon over time? – dave adelson Apr 17 '22 at 18:33
  • Don't think that this should be an issue as under the hood `geom_col_interactive` calls `GeomColInteractive`. – stefan Apr 17 '22 at 18:39
0

Here are a workaround for not using GeomInteractiveCol() and an alternative/shortcut to after_stat() :

library(ggplot2)
library(ggiraph)

tooltip <- function(y, ymax, accuracy = .01) {
  mean <- scales::number(y, accuracy = accuracy)
  sem <- scales::number(ymax - y, accuracy = accuracy)
  paste("Mean mpg:", mean, "+/-", sem)
}

gg_point <- ggplot(mpg) +
  aes(x = as.factor(cyl), fill = as.factor(cyl), y = hwy, 
    tooltip = tooltip(..y.., ..ymax..)
  ) +
  geom_bar_interactive(fun.data = "mean_se", stat = "summary") +
  geom_errorbar_interactive(fun.data = "mean_se", stat = "summary", 
    width = 0.2, size = 0.2
  )

girafe(ggobj = gg_point)

I personally prefer to use the geom_ grammar rather than the stat_ one, because it is more consistent with the rest of ggplot code.

And here is a way of doing so in one command with glue(), but for an unknown reason, it still necessitates after_stat():

{ggplot(mpg) +
  aes(x = as.factor(cyl), fill = as.factor(cyl), y = hwy, 
    tooltip = glue("Mean mpg: {round(y, 2)} +/- {round(ymax, 2)}") %>% after_stat()
  ) +
  geom_bar_interactive(fun.data = "mean_se", stat = "summary") +
  geom_errorbar_interactive(fun.data = "mean_se", 
    stat = "summary", width = 0.2, size = 0.2)
  } %>% 
  girafe(ggobj = .)
doana
  • 35
  • 4
  • I've been trying to find documentation on the ..y.. syntax (which I have not seen before) without success (incl at the tidyverse and ggplot docs)...can you point me to a source for understanding it? – dave adelson Apr 21 '22 at 15:57
  • Pffiu it was hard to remember where I've found this : https://ggplot2-book.org/statistical-summaries.html. I think it is simply a shortcut around `after_stat()`. – doana Apr 22 '22 at 13:50
  • tx! it's remarkably hard to use search engines to find .. ;) – dave adelson Apr 22 '22 at 17:19
  • closest i found was here: https://github.com/Rdatatable/data.table/blob/master/NEWS.md#changes-in-v1102--on-cran-31-jan-2017 ...where they point out: "?".", ?"..", ?".(", and ?".()" now point to ?data.table, #4385 #4407. To help users find the documentation for these convenience features available inside DT[...]. Recall that . is an alias for list, and ..var tells data.table to look for var in the calling environment as opposed to a column of the table." – dave adelson Apr 22 '22 at 17:22