Search code examples
rggplot2t-test

R: t.test in a facet_grid (ggplot)


This is a very specific question, but I already have and use this detailed and well working code, so I hope to find the minor change it takes to adjust it and make it work for the next level of complexity. What I got:

library(ggplot2)
library(ggpubr)
head(ToothGrowth)
ToothGrowth$dose <- as.factor(ToothGrowth$dose)
# add a grouping ID for measured individuals:
ToothGrowth$ID <- rep(c(1:30),2)

# The code I am using now (basically a solution I got from my former question answered by Allan Cameron (user:12500315)):
ggplot(ToothGrowth, aes(supp, len, fill = dose, alpha = supp)) +
  geom_boxplot() +
  scale_fill_manual(name   = "Dosis", 
                    labels = c("0.5", "1", "2"), 
                    values = c("darkorange2", "olivedrab", "cadetblue4")) +
  scale_alpha_discrete(range = c(0.5, 1), 
                       guide = guide_none()) +
  geom_line(inherit.aes = FALSE, 
            aes(supp, len, group = ID), 
            color = "gray75") +
  geom_text(data = data.frame(
    x    = 1.5, 
    y    = 40, 
    dose = c("0.5", "1", "2"),
    pval = sapply(c("0.5", "1", "2"), function(x) {
      round(t.test(len ~ supp, 
                   data = ToothGrowth[ToothGrowth$dose == x,],
                   paired = TRUE)$p.val, 4)})), 
    inherit.aes = FALSE,
    aes(x = 1.5, y = 40, label = paste("T test: p value =", pval)), 
    check_overlap = TRUE) +
  facet_grid(~dose) +
  theme_classic() +
  theme(legend.position = "top",
        strip.background = element_rect(fill = "gray95", size = 0.25))

# Follow-up question:
# What I want to do next: having another facetting variable ('researcher')
ToothGrowth_1 <- ToothGrowth
# create a random numerical factor to multiply measures with and then enlarge the dataset by a second set of measurements from a different 'researcher':
r <- runif(60, min=0, max=3)
ToothGrowth_1$len <- ToothGrowth_1$len*r
ToothGrowth$researcher <- "A"
ToothGrowth_1$researcher <- "B"
ToothGrowth_total <- rbind(ToothGrowth, ToothGrowth_1)

Now, I would like to plot the same plot like above, but have horizontal facet splitting for the two 'researcher' groups (A vs B). I figured out a work-around by creating and interaction term of 'researcher' and 'dose' and replacing the facet_grid by a facet_wrap, but I would rather see the solution with facet_grid, as it makes everything else easier from there on. Thanks for helping, much appreciated!


Solution

  • Thanks for posting the follow-up.

    The natural way to do this would be to map the two levels, though I think rather than a full rewrite to accomplish this, I would probably just concetenate 2 sapply calls - one for each level of the new factor:

    ggplot(ToothGrowth_total, aes(supp, len, fill = dose, alpha = supp)) +
      geom_boxplot() +
      scale_fill_manual(name   = "Dosis", 
                        labels = c("0.5", "1", "2"), 
                        values = c("darkorange2", "olivedrab", "cadetblue4")) +
      scale_alpha_discrete(range = c(0.5, 1), 
                           guide = guide_none()) +
      geom_line(inherit.aes = FALSE, 
                aes(supp, len, group = ID), 
                color = "gray75") +
      geom_text(data = data.frame(
        x    = 1.5, 
        y    = c(40, 40, 40, 70, 70, 70), 
        researcher = c("A", "A", "A", "B", "B", "B"),
        dose = c("0.5", "1", "2", "0.5", "1", "2"),
        pval = c(sapply(c("0.5", "1", "2"), function(x) {
                round(t.test(len ~ supp, 
                data = subset(ToothGrowth_total, dose == x & researcher == "A"),
                paired = TRUE)$p.val, 4)}), 
                sapply(c("0.5", "1", "2"), function(x) {
                round(t.test(len ~ supp, 
                data = subset(ToothGrowth_total, dose == x & researcher == "B"),
                paired = TRUE)$p.val, 4)}))),
        inherit.aes = FALSE,
        aes(x = x, y = y, label = paste("T test: p value =", pval)), 
        check_overlap = TRUE) +
      facet_grid(researcher~dose, scales = "free_y") +
      theme_classic() +
      theme(legend.position = "top",
            strip.background = element_rect(fill = "gray95", size = 0.25))
    

    enter image description here