0

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 :)

1 Answer 1

0

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)
  )

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you so much for the quick answer! If you have the time, I don't think I got how to reorder. Did you mean: "d1 <- d %>% select(-Weight (gm)) %>% pivot_longer(-Rodent) |> mutate( name = factor(name, levels=c("Heat","Needle","Comb")) )" ? Thanks again.
Almost. Do factor(name, levels=c("Comb:", "Needle:", "Heat:")), i.e. you have to include the colon and you have to reverse the order to put Heat on top aka last. Scales always start with "1" aka the first category. That's why I used rev(). And using unique() is a small trick. That will return the categories in the order as they appear in the data, i.e. factor(x, unique(x)) is the same as forcats::fct_inorder(x).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.