4

I am trying to make striped plots (with altering white and grey background) when plotting 5 box plots in a row. Why is the background color not being applied to the whole plot in my code? The background color does change when I plot the box plots individually.

set.seed(42)
dev.off()
windows(width=6, height=4)
par(mfrow=c(1,5))
par(mar=c(2,4,1,1)) # bottom, left, top and right

par(bg = 'white')
boxplot(rnorm(20), ylab = "A")
title(xlab="n = 54", line=0)

par(bg = 'grey')
boxplot(rnorm(20),  ylab = "B")
title(xlab="n = 54", line=0)

par(bg = 'white')
boxplot(rnorm(20),  ylab = "C")
title(xlab="n = 54", line=0)

par(bg = 'grey')
boxplot(rnorm(20),  ylab = "D")
title(xlab="n = 26", line=0)

par(bg = 'white')
boxplot(rnorm(20),  ylab = "E")
title(xlab="n = 6", line=0)

To clarify, I want the area inside red rectangles in the figure below to be grey.

enter image description here

3
  • I am not sure what you are asking, but this might help: stackoverflow.com/questions/14604439/… Your code suggests to me that you are interested in the fill color of the box plot rather than the background color of the plot. Commented Jan 11, 2017 at 23:23
  • 1
    So not just the plot area as in my solution, but the whole region Commented Jan 11, 2017 at 23:40
  • 1
    BTW, the appearance of mine can be improved by adding col="white" to the second time you print the boxplots with the grey backgrounds Commented Jan 12, 2017 at 0:00

3 Answers 3

3

Sorry, This is not pretty, but I fear that it all that you can do.

As you discovered bg merely controls the background color of the box itself, not the whole plot. This solution has the ugly feature of plotting the data twice. Once to get where everything will be plotted, using that to display a background rectangle, then plotting the data again. But I believe that this is what you were looking for.

set.seed(42)
dev.off()
windows(width=6, height=4)
par(mfrow=c(1,5))
par(mar=c(2,4,1,1)) # bottom, left, top and right

Data = rnorm(20)
boxplot(Data,  ylab = "A")
rect(par("usr")[1],par("usr")[3],par("usr")[2],par("usr")[4],col = "white")
boxplot(Data,  ylab = "A", add=TRUE)
title(xlab="n = 54", line=0)

Data = rnorm(20)
boxplot(Data,  ylab = "B")
rect(par("usr")[1],par("usr")[3],par("usr")[2],par("usr")[4],col = "grey")
boxplot(Data,  ylab = "B", add=TRUE)
title(xlab="n = 54", line=0)

Data = rnorm(20)
boxplot(Data,  ylab = "C")
rect(par("usr")[1],par("usr")[3],par("usr")[2],par("usr")[4],col = "white")
boxplot(Data,  ylab = "C", add=TRUE)
title(xlab="n = 54", line=0)

Data = rnorm(20)
boxplot(Data,  ylab = "D")
rect(par("usr")[1],par("usr")[3],par("usr")[2],par("usr")[4],col = "grey")
boxplot(Data,  ylab = "D", add=TRUE)
title(xlab="n = 26", line=0)

Data = rnorm(20)
boxplot(Data,  ylab = "E")
rect(par("usr")[1],par("usr")[3],par("usr")[2],par("usr")[4],col = "white")
boxplot(Data,  ylab = "E", add=TRUE)
title(xlab="n = 6", line=0)

Boxplots with background

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

Comments

2

Here's a ggplot alternative which requires less hard-coding.

library(ggplot2)
library(gridExtra)

df <- data.frame(grp = rep(letters[1:5], c(12, 8, 11, 9, 10)), y = rnorm(50))

grp <- unique(df$grp)
cols <- c("grey80", "white")

l <- vector(length = length(grp), "list")

for(i in seq_along(grp)){
  dat <- df[df$grp == grp[i], ]
  col <- cols[i %% 2 + 1]
  p <- ggplot(dat) +  
    geom_boxplot(aes(x = factor(1), y = y), fill = col) +
    theme(plot.background = element_rect(fill = col),
          panel.background = element_rect(fill = col),
          panel.border = element_rect(fill = NA, colour = "black"),
          panel.grid = element_blank()) +
    scale_x_discrete(breaks = NULL) +
    xlab(paste0(grp[i], "\n", "n = ", nrow(dat)))
  l[[i]] <- p
}

do.call(grid.arrange, c(l, nrow = 1))

enter image description here


Explanation:

  1. Put the values used for the plots in a data.frame with a relevant grouping variable ('grp') which distinguishes the values
  2. Create a vector of unique groups ('grp'), pre-allocate a list ('l') to store the plots in, and set the desired fill colors ('cols')
  3. Loop over the indices of the groups (for(i in seq_along(grp)))
  4. Subset the data based on group (df[df$grp == grp[i], ])
  5. Select background color using a numeric vector indicating odd / even values of the group indices (i %% 2 + 1), to alternate grey and white background.
  6. Plot (ggplot)
  7. Fill relevant elements with 'col'. Modify other theme elements according to taste
  8. Create x labels (xlab) dynamically: grab current 'grp' and calculate sample size (nrow(dat))
  9. Assign the plot to its list element (l[[i]] <- p)
  10. Use gridExtra::grid.arrange to render and arrange the plots in the list
  11. Voilà!

Comments

1

This is the best I have been able to come up with. I had to approximate the four corners of each rectangle by trial-and-error. I commented out the three white rectangles without sizing them properly, but retained the code to show they could be included with a desired color.

setwd('C:/Users/general1/Documents/simple R programs/')

jpeg(filename = "boxplot_background_color_with_layout.jpeg")

set.seed(1223)
par(xpd = NA, mar = c(2,4,1,1), bg = 'white')
layout(matrix(c(1,2,3,4,5), 1, 5, byrow = TRUE))

boxplot(rnorm(20), ylab = "A")
title(xlab="n = 54", line=0)
#rect(-1, -2.375, 1.585, 2, col = rgb(0,0,0,alpha=0.5), border=FALSE) 

boxplot(rnorm(20), ylab = "B")
title(xlab="n = 54", line=0)
rect(-0.4, -2.229, 1.6, 2.0, col = rgb(0.5,0.5,0.5,alpha=0.5), border=FALSE) 

boxplot(rnorm(20), ylab = "C")
title(xlab="n = 54", line=0)
#rect(-1, -2.375, 1.585, 2, col = rgb(0,0,0,alpha=0.5), border=FALSE)

boxplot(rnorm(20), ylab = "D")
title(xlab="n = 54", line=0)
rect(-0.4, -2.5, 1.6, 2.5, col = rgb(0.5,0.5,0.5,alpha=0.5), border=FALSE) 

boxplot(rnorm(20), ylab = "E")
title(xlab="n = 54", line=0)
#rect(-1, -2.375, 1.585, 2, col = rgb(0,0,0,alpha=0.5), border=FALSE)

dev.off()

enter image description here

Comments

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.