How to put the correct graphs from a list with ggarrange in the same image

62 Views Asked by At

from the data: https://drive.google.com/file/d/1t4D9PothEcbcGtV-eELzv6mji4y5lepk/view?usp=sharing, that contain the normalized counts of 28 species of beetles in different locations (the sp column).

For an immediate visualization of the data, I want to generate boxplots: 2 (the 2 conditions, A and K) for every species in the dataset (the columns). And then save all the graphics in the same image, but with ggarrange, all i obtain is an image with 28 graphs (good) but they are all the same, except for the ylabels which seems to be the only correct things.

library(viridis)
library("ggpubr")
library(stringr)

beetles<- read.csv("beetles.csv", header=TRUE)
beetles$sp2<- str_replace_all(beetles$sp, "[:digit:]", "")
beetles$sp3<- gsub("^K.+","K", gsub( "^A.+", "A",beetles$sp) )


specie<- colnames(beetles[2:29])

plot_list = list()
for (i in seq_along(specie)) {
    tmpS<- specie[i]
    p = ggplot(beetles, aes(x = sp3, y = beetles[,tmpS], fill = factor(sp3))) +
  geom_boxplot(outlier.colour = NA) +
  scale_fill_viridis(discrete = TRUE, alpha = 0.6) +
  geom_point(aes(color = sp, group = factor(sp2)), 
             size = 1, 
             position = position_jitterdodge(0.25, 0, 0.75)) +
  stat_compare_means(method = "t.test") +
  #hrbrthemes::theme_ipsum() +
  theme(plot.title = element_text(size = 11))+
    labs(x = NULL, y=tmpS, fill = 'sp3', title = "A boxplot with jitter") 
    print(p)
    plot_list[[tmpS]] = p
}

k<- ggarrange(
  plotlist = plot_list,
  ncol = 7,
  nrow = 4,
  common.legend = TRUE
)

ggsave("boxes.pdf", plot=k, width=20, height=20) 

the output

what I am doing wrong?

2

There are 2 best solutions below

2
HoelR On BEST ANSWER

Perhaps you are looking for facet_wrap()

library(tidyverse)
library(ggpubr)

df <- read_csv("beetles.csv")

df %>%  
  pivot_longer(!sp) %>%  
  mutate(sp2 = str_remove_all(sp, "[:digit:]"), 
         sp3 = str_extract(sp, "^.")) %>% 
  ggplot() + 
  aes(x = sp3, y = value, fill = sp3) + 
  geom_boxplot() + 
  geom_point(aes(col = sp, 
                 group = sp2), 
             size = 1, 
             position = position_jitterdodge(0.25, 0, 0.27)) +
  stat_compare_means(method = "t.test", vjust = 1) + 
  facet_wrap(~ name, scales = "free") + # <- Key function to split plots
  theme(legend.position = "top") + 
  labs(title = "Boxplots with jitter", 
       subtitle = "Subtitle")

enter image description here

0
jared_mamrot On

I think the issue is the y = beetles[,tmpS]; if you change it to .data[[tmpS]] it should hopefully work as expected, e.g. using the built-in mtcars dataset:

library(tidyverse)

mtcars_cols <- colnames(mtcars[c(1,3,4,5,6,7)])
plot_list <- list()
for (i in seq_along(mtcars_cols)) {
  tmpS <- mtcars_cols[i]
  p = ggplot(mtcars, aes(x = cyl, y = .data[[tmpS]], fill = factor(vs))) +
    geom_boxplot(outlier.colour = NA)
#  print(p)
  plot_list[[tmpS]] = p
}

ggpubr::ggarrange(plotlist = plot_list)

Created on 2024-02-05 with reprex v2.1.0

Data masking (i.e. using .data) is meant to reduce ambiguity in code (see e.g. https://rlang.r-lib.org/reference/topic-data-mask-ambiguity.html) but it can be hard to understand how and when to use it. Advanced R has a chapter on 'evaluation' that explains it in more detail: https://adv-r.hadley.nz/evaluation.html?q=data%20mask#data-masks