0
votes

The following R code shows a demo ggplot2 extension. This extension displays a star at a specified x-axis group (option ref.group).

In the StatShowStarsAt ggproto code, the user specified ref.group is mapped to the transformed data value in the aesthetic space, using ref.group <- scales$x$map(ref.group).

For grouped plots, does something similar exist for mapping legend group in the aesthetic space? For example, legend.group <- scales$legend$map(legend.group), where legend.group can be color or fill scale.

# ggplot2 extension: demo
library(ggplot2)
stat_show_stars_at <- function(mapping = NULL, data = NULL, geom = "text", position = "identity",  
                            na.rm = FALSE, show.legend = NA, inherit.aes = TRUE, ref.group = NULL, ...){
  layer(
    stat = StatShowStarsAt, data = data, mapping = mapping, geom = geom,
    position = position, show.legend = show.legend, inherit.aes = inherit.aes,
    params = list(ref.group = ref.group, ...)
  )
}

StatShowStarsAt <- ggproto("StatShowStarsAt", Stat,
                           required_aes = c("x", "y"),
                           
                           compute_panel = function(self, data, scales, ref.group)
                           {
                             if(!is.null(ref.group)) {
                               ref.group <- scales$x$map(ref.group)
                             }
                             data.frame(
                               x = ref.group,
                               y = scales$y$range$range[2],
                               label = "*"
                             )
                           }
)


# Usage
ggplot(PlantGrowth, aes(group, weight)) +
  geom_boxplot() +
  stat_show_stars_at(ref.group = "trt2", color = "red", size = 10)

1
It's not clear what you mean by "legend group". There are various different scales in ggplot: the x position scale and the y position scale are not displayed in a legend, but the color scale, fill scale, size scale, shape scale, alpha scale and radius scales can be. Have you looked at the extending ggplot vignette?Allan Cameron
Clarified now, thanks! Yes I read the ggplot vignette and can't find the solution.A. Kassambara
Can you give an example of what you're trying to do? You don't need to extend ggplot to map individual colours, fills etc to scales. You can do this directly in ggplot. Or am I misunderstanding you?Allan Cameron
I would like to create a ggplot extension that automatically compute a pairwise t-test between a user specified reference group and the remaining groups on the plot, and shows significance stars as described at: datanovia.com/en/blog/…. As you know, ggplot automatically transforms original factor levels ("0.5", "1", "2") into numeric vector (1, 2, 3). How can I find the numeric Id of ref.group = "0.5" when group is a legend variable?A. Kassambara

1 Answers

1
votes

If you pass in the factor variable as a new aesthetic mapping you can compute the x position from that:

StatShowStarsAt <- ggproto("StatShowStarsAt", Stat,
                     required_aes = c("x", "y", "test"),
                     
                     compute_panel = function(self, data, scales, ref.group)
                     {
                       df <- data[data$test == ref.group,]
                       group_lev <- unique(as.numeric(df$test))
                       wid <- 1/(length(levels(data$test)) + 1)
                       offset <- wid * (group_lev - median(seq_along(levels(data$test))))
                       data.frame(
                         x = unique(df$x) + offset,
                         y = sapply(unique(df$x), function(i) max(df$y[df$x == i])),
                         label = "*",
                         group = unique(as.numeric(df$test))
                       )
                     }
)

So for example, if we create a dataset that better matches your link:

PG <- rbind(PlantGrowth, 
            within(PlantGrowth, weight <- weight + rnorm(length(weight))))
PG$time <- factor(rep(1:2, each = nrow(PlantGrowth)))

We can do:

ggplot(PG, aes(time, weight, color = group)) +
  geom_boxplot() +
  stat_show_stars_at(aes(test = group), ref.group = "trt2", color = "red", size = 10)

enter image description here

ggplot(PG, aes(time, weight, color = group)) +
  geom_boxplot() +
  stat_show_stars_at(aes(test = group), ref.group = "ctrl", color = "red", size = 10)

enter image description here

Note - I have written this to work with three groups just to show the principle. The details of fixing the x position for arbitrary group sizes is just a matter of geometry and trial-and-error.