How to create multiple ggboxplots on the same graph using the loop function?

Viewed 437

TL;DR: Trying to create multiple boxplots using ggboxplot in one graph (images attached), using loop function. Currently manually creating codes for each boxplot, then using either ggarrange() or par() function to plot them together. It works, but looking for a less repetitive way.

I was wondering if it's possible to create multiple ggboxplots using a loop function. I've seen multiple replies/solutions on StackOverflow but none of them quite accurately captured the solution I was looking for (or that it generally was not necessary to use a loop function).

My data looks something like this:

# A tibble: 62 x 4
   offer payoff  partner_transfer  round_type
   <dbl>  <dbl>       <dbl>         <chr>     
 1    40    126        66           actual    
 2   100    273       273           actual    
 3     0    100        0            actual    
 4   100      6        6            actual    
 5    25     99       24            actual    
 6    80     29        9           practice    
 7   100     45       45           practice    
 8     0    100        0           practice    
 9    25     99       24           practice    
10   100    183       183          practice    
# ... with 52 more rows

The output I'm trying to get is this:

boxplots output

I was able to get that by running multiple codes, and then using ggarrange() function to combine them (below):

box_offer <- ggboxplot(data = tg_proposer_split, x = "round_type", y = "offer",
                   fill = "round_type",
                   palette = "ucscgb",
                   ylab = "Offer (by A)", xlab = "Round Type",
                   add = "jitter",
                   shape = "round_type")

box_partner_transfer <- ggboxplot(data = tg_proposer_split, x = "round_type", y = "partner_transfer",
                   fill = "round_type",
                   palette = "ucscgb",
                   ylab = "Amount Transferred by Partner (Bot)", xlab = "Round Type",
                   add = "jitter",
                   shape = "round_type")

box_payoff <- ggboxplot(data = tg_proposer_split, x = "round_type", y = "payoff",
                       fill = "round_type",
                       palette = "ucscgb",
                       ylab = "Payoff (for A)", xlab = "Round Type",
                       add = "jitter",
                       shape = "round_type")

ggarrange(box_offer, box_partner_transfer, box_payoff, 
          labels = c("A", "B", "C"),
          ncol = 2, nrow = 2)

Another way that I'm going about this is by using the par() function (but to plot means). Image here:

plotmeans sample

The code I used for this is:

par(mfrow = c(2,2))

plot_offer <- plotmeans( offer ~ round_type, data = tg_proposer_split,
          xlab = "Round Type", ylab = "Offer (by A)",
          main="Mean Plot with 95% CI") 

plot_partner_transfer <- plotmeans( partner_transfer ~ round_type, data = tg_proposer_split,
          xlab = "Round Type", ylab = "Amount Transferred by Partner (Bot)",
          main="Mean Plot with 95% CI") 

plot_payoff <- plotmeans( payoff ~ round_type, data = tg_proposer_split,
          xlab = "Round Type", ylab = "Payoff (for A)",
          main="Mean Plot with 95% CI") 

While using either ggarrange() or par() gives me exactly what I want, it's a bit too cumbersome, as sometimes I have over 10 columns/variables that I want to create boxplots for. Hence I'm trying to find some luck here if there is a shorter way to get the output I want without being repetitive in my code. I'm not sure if the problem lies in the way I organised my dataset that is making this process difficult but either way, I'm open to different solutions.

1 Answers

You can use Map to create list of plots and use ggarrange to plot it. Pass column names and y-labels separately.

library(ggpubr)

cols <- setdiff(names(tg_proposer_split), 'round_type')
y_labels <- c("Offer (by A)", "Amount Transferred by Partner (Bot)", "Payoff (for A)")

Map(function(x, y) {
  ggboxplot(data = tg_proposer_split, x = "round_type", y = x,
            fill = "round_type",
            palette = "ucscgb",
            ylab = y, xlab = "Round Type",
            add = "jitter",
            shape = "round_type")
}, cols, y_labels) -> list_plots

ggarrange(plotlist = list_plots, common.legend = TRUE)

enter image description here

data

tg_proposer_split <- structure(list(offer = c(40L, 100L,0L,100L, 25L, 80L,100L, 
0L, 25L, 100L), payoff = c(126L, 273L, 100L, 6L, 99L, 29L, 45L, 
100L, 99L, 183L), partner_transfer = c(66L, 273L, 0L, 6L, 24L, 
9L, 45L, 0L, 24L, 183L), round_type = c("actual", "actual", "actual", 
"actual", "actual", "practice", "practice", "practice", "practice", 
"practice")), class = "data.frame", row.names = c(NA, -10L))
Related