rggplot2geom-textpatchwork

How to modify text to ggplot below the plot?


Much like a previous user , I would like a panel of text underneath my plot.

With the previous post, I have gotten pretty far, but I would still like to modify my plot. With dummy data (borrowed from the previous post), my plot looks like this: Current plot

library(patchwork)
line_size <- 1.2 
base_size <- 20 
axis_text_rel_size = -1
title_text_rel_size = 5

d <- tibble(
  Rodent= c(rep("Mouse",11),
            rep("Hamster",7),
            rep("Guinea pig",4),
            rep("Gerbil",12)),
  `Weight (gm)` = rnorm(34,25,10),
  `Heat:` = c(rep("+",11),rep("-",7),rep("+",4),rep("+",12))
  ,  `Needle:` = c(rep("+",11),rep("+",7),rep("+",4),rep("+",12)),
  `Comb.:` = c(rep("Phen",11),rep("-",7),rep("-",4),rep("Met",12)),
)

p1 <- d %>% 
  ggplot(aes(Rodent,`Weight (gm)`)) +
  geom_boxplot(lwd=1.3,colour="black")+
  scale_y_continuous(expand = expansion(mult = c(0, 0.05)))+
  labs(y = "Percentage") +
  theme_foundation(base_size = base_size, base_family = "sans")+ 
  theme(
    panel.grid.major = element_blank(),
    panel.grid.minor = element_blank(),
    panel.border = element_blank(),
    panel.background = element_blank(),
    text = element_text(colour = "black"),
    plot.title = element_text(face = "bold", 
                              size = rel(1), hjust = 0.5),
    axis.line = element_line(colour="black", size = line_size),
    axis.ticks = element_line(colour="black", size = line_size),
    axis.title = element_text(face = "bold", size = rel(1)),
    axis.title.y = element_text(angle = 90, vjust = 2),
    axis.title.x = element_blank(),
    axis.text = element_text(face = "bold", size = rel(1)),
    axis.text.x = element_blank(),
    plot.background = element_blank(),
    legend.title=element_blank(),
    legend.position = "none"
  )

d1 <- d %>% 
  select(-`Weight (gm)`) %>%
  pivot_longer(-Rodent)

p2 <- d1 %>% 
  ggplot(aes(Rodent, fct(name), label = value)) +
  geom_text(size = 7.2) +
  labs(x = NULL, y = NULL)+
  theme_foundation(base_size = base_size, base_family = "sans")+
  theme(
    panel.grid.major = element_blank(),
    panel.grid.minor = element_blank(),
    panel.border = element_blank(),
    panel.background = element_blank(),
    text = element_text(colour = "black"),
    axis.title = element_text(face = "bold", size = rel(0.9)),
    axis.title.y = element_text(angle = 90, vjust = 2),
    axis.text = element_text(face = "bold", size = rel(1)),
    axis.text.x = element_blank(),
    axis.ticks=element_blank(),
    plot.background = element_blank()
  )


p1 / p2

If it is possible, I would like the panel to go Heat > Needle > Comb, but I don't know where to refactor. I would also like to reduce the spacing between the three "treatment options" (Heat, needle, comb) as well as the spacing between the y-axis and its title. Also, the fonts in the panel seem to differ depending whether its a header or not.

I am not married to this code, so if there is an easier way to get a panel below the plot, I would really appreciate it! Thank you :)


Solution

  • To achieve your desired order for the table convert name in d1 to a factor with the levels set in your desired order. For the labels use the same font size as for theme, i.e. 20 / .pt or 20pt instead of 7.2 which is approx. 20.5 pt. To remove the space between the axis title and the axis text you could set `vjustĀ“ to a negative value. Additionally I use a negative plot margin on the left. For the spacing between the table categories a simple option would be to increase the size of the main plot. This way the table gets squished. Finally, I collected the duplicated theme options and apply them in one go where creating the patch.

    library(patchwork)
    library(ggplot2)
    library(ggthemes)
    library(tidyr)
    library(forcats)
    library(dplyr, warn = FALSE)
    
    set.seed(123)
    
    p1 <- d %>%
      ggplot(aes(Rodent, `Weight (gm)`)) +
      geom_boxplot(lwd = 1.3, colour = "black") +
      scale_y_continuous(expand = expansion(mult = c(0, 0.05))) +
      labs(y = "Percentage") +
      theme_foundation(base_size = base_size, base_family = "sans") +
      theme(
        plot.title = element_text(
          face = "bold",
          size = rel(1), hjust = 0.5
        ),
        axis.line = element_line(colour = "black", size = line_size),
        axis.ticks = element_line(colour = "black", size = line_size),
        axis.title.x = element_blank(),
        legend.title = element_blank(),
        legend.position = "none"
      )
    
    d1 <- d %>%
      select(-`Weight (gm)`) %>%
      pivot_longer(-Rodent) |>
      mutate(
        name = factor(name, rev(unique(name)))
      )
    
    p2 <- d1 %>%
      ggplot(aes(Rodent, name, label = value)) +
      geom_text(size = 20 / .pt) +
      labs(x = NULL, y = NULL) +
      theme_foundation(base_size = base_size, base_family = "sans") +
      theme(
        axis.ticks = element_blank()
      )
    
    
    (p1 / p2) +
      plot_layout(heights = c(2, 1)) &
      theme(
        panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(),
        panel.border = element_blank(),
        panel.background = element_blank(),
        text = element_text(size = 20, colour = "black"),
        axis.title = element_text(face = "bold", size = rel(1)),
        axis.title.y = element_text(angle = 90, vjust = -8),
        axis.text = element_text(face = "bold", size = rel(1)),
        axis.text.x = element_blank(),
        plot.background = element_blank(),
        plot.margin = margin(5.5, 5.5, 5.5, -5.5)
      )