Stella
Stella

Reputation: 73

R multiple boxplots in one plot

I have a question regarding multiple boxplots. Assume we have data structures like this:

a <- rnorm(100, 0, 1)
b <- rnorm(100, 0, 1)
c <- rbinom(100, 1, 0.5)

My task is to create a boxplot of a and b for each group of c. However, it needs to be in the same plot. Ideally: Boxplot for a and b side by side for group 0 and next to it boxplot for a and b for group 1 and all together in one graphic.

I tried several things, but only the seperate plots are working:

boxplot(a~as.factor(c))
boxplot(b~as.factor(c))

But actually, that's not what I'm searching for. As it has to be one plot.

Upvotes: 1

Views: 2712

Answers (3)

Bernhard
Bernhard

Reputation: 4417

Noah has already given the ggplot2 answer that would also be my go to option. As you used the boxplot function in the question, this is how to approach it with boxplot. You should probably stay consistently within base or within ggplot2 for your publication/presentation.

First we transform the data to a long format (here an option without additional packages):

a <- rnorm(100, 0, 1)
b <- rnorm(100, 0, 1)
c <- rbinom(100, 1, 0.5)
d <- data.frame(a, b, c)
d <- cbind(stack(d, select = c("a", "b")), c)

giving us

> head(d)
       values ind c
1 -0.66905293   a 0
2 -0.28778381   a 0
3  0.29148347   a 1
4  0.81380406   a 0
5 -0.85681913   a 0
6 -0.02566758   a 0

With which we can then call boxplot:

boxplot(values ~ ind + c, data = d, at = c(1, 2, 4, 5))

Grouped boxplot with base graphics

The at argument controls the grouping and placement of the boxes. Contrary to ggplot2 you need to choose placing manually, but you also get very fine control of spacing very easily.

Slightly refined version of the plot:

boxplot(values ~ ind + c, data = d, at = c(1, 2, 4, 5),
        col = c(2, 4), show.names = FALSE,
        xlab = "")
axis(1, labels= c("c = 0", "c = 1"), at = c(1.5, 4.5))
legend("topright", fill = c(2, 4), legend = c("a", "b"))

enter image description here

Upvotes: 2

Quinten
Quinten

Reputation: 41225

Another option using lattice package with bwplot function:

library(tidyr)

a <- rnorm(100, 0, 1)
b <- rnorm(100, 0, 1)
c <- rbinom(100, 1, 0.5)

df <- data.frame(a = a,
                 b = b,
                 c = c)

# make longer dataframe
df_long <- pivot_longer(df, cols = -c)

library(lattice)
bwplot(value ~ name | as.factor(c), df_long)

Created on 2022-08-19 with reprex v2.0.2

Upvotes: 1

Noah
Noah

Reputation: 440

You can use the tidyverse package for this. You transform your data into long-format that you get three variables: "names", "values" and "group". After that you can plot your boxplots with ggplot():

value_a <- rnorm(100, 0, 1)
value_b <- rnorm(100, 0, 1)
group <- as.factor(rbinom(100, 1, 0.5))

data <- data.frame(value_a,value_b,group)

library(tidyverse)

data %>%
  pivot_longer(value_a:value_b, names_to = "names", values_to = "values") %>%
  ggplot(aes(y = values, x = group, fill = names))+
  geom_boxplot()

Created on 2022-08-19 with reprex v2.0.2

Upvotes: 2

Related Questions