1

I want to create a boxplot with two y axis (both continuous with different scales) and a factor as x axis. Ideally, there should be a box of each continuous variable for each level of the factor. I would need a boxplot like this one, described in the first answer of this question. But in R.

So far, I adapted the code in this example to include boxplots and dotplots. However, I can´t make the plots of the second variable appear next to the previous ones instead of underneath.

data <- data.frame(Factor1=factor(c("A", "B","A", "B","A", "B","A", "B", "A", "B","A",     "B","A", "B","A", "B", "A", "B","A", "B", "A", "B", "A", "B","A", "B", "A", "B","A", "B","A",     "B","A", "B", "A", "B")), Cont1=rnorm(36, mean=100, sd= 15), Cont2=rnorm(36, mean=0.35, sd=0.05))

par(mar=c(5, 4, 4, 6) + 0.5)

## Plot first continuous variable
# Boxplot
boxplot(Cont1 ~ Factor1, data = data, col="white", boxcol=2, xlim=c(0.5, 3.5 + length(unique(data$Factor1))),axes=FALSE, xlab="", ylab="")

# Points
stripchart(Cont1 ~ Factor1, data = data,method = "jitter",pch = 19,col = 2,vertical = TRUE,add = TRUE)

mtext("Cont1", side=2, line=2.5, col=2)
box()
axis(2, col=2, col.axis=2,las=1)  ## las=1 makes horizontal labels


## Allow a second plot on the same graph
par(new=TRUE)

## Plot the second continuous variable
# Boxplot
boxplot(Cont2 ~ Factor1, data = data, col="white", boxcol=3,xlim=c(0.5, 5.5), axes=FALSE, xlab="", ylab="") # with these limits the new boxplot and dotplot shows up below the previous ones, rather than next to them

# Points
stripchart(Cont2 ~ Factor1, data = data,method = "jitter", pch = 19, col = 3, vertical = TRUE, add = TRUE)
## a little farther out (line=4) to make room for labels
mtext("Cont2", side=4,col=3,line=4) 
axis(4, col=3,col.axis=3,las=1)

## Draw the factor axis
mtext("Factor1", side=1, col="black", line=2.5)  

I would be happy hearing about how to improve this code, but also with new suggestions.

Thanks!
Teresa
  • 15
  • 3

1 Answers1

0

So given you want to use base R I would propose the following:

Transform your data to be represented on the second y-axis so that it is in the ballpark of the first axis and remember that scalar. So if using base R we need to do some transformation. There are better ways to do that then below, but time...

data <- data.frame(
  Factor1 = factor(rep(c("A", "B"), times = 18)),
  Cont1 = rnorm(36, mean=100, sd= 15),
  Cont2 = rnorm(36, mean=0.35, sd=0.05)
)

vec1 <- data$Cont1[data$Factor1 == "A"]
vec2 <- data$Cont1[data$Factor1 == "B"]
vec3 <- data$Cont2[data$Factor1 == "A"] * 300
vec4 <- data$Cont2[data$Factor1 == "B"] * 300

datn <- as.data.frame(cbind(vec1, vec2, vec3, vec4))
head(datn)

Draw a grouped boxplot without axes.

par(mar=c(5, 4, 4, 6) + 0.5)

boxplot(
  x = datn,
  axes = FALSE,
  ylim = c(0, 300),
  col = rep(c("lightcyan", "salmon"), times = 2),
  border = "gray25"
)

Manually add axis. When Adding the second axis (side = 4) transform labels so that they show data in the original scale.

axis(
  side = 1,
  at = c(1.5, 3.5),
  labels = c("Cont1", "Cont2")
)

axis(
  side = 2,
  at = seq(0, 300, 100),
  labels = seq(0, 300, 100),
  las = 2
)

axis(
  side = 4,
  at = seq(0, 300, 100),
  labels = round(seq(0, 300, 100) / 300, digits = 2),
  las = 2
)

box(which = "plot")

Lastly add points of stripchart.

stripchart(
  x = datn,
  method = "jitter",
  pch = 19,
  col = "lightgreen",
  vertical = TRUE,
  add = TRUE
)

This should give (unformatted):

enter image description here

The edited code should then result in the following graph (partly formatted):

enter image description here

Markus_J
  • 51
  • 4
  • thanks for your answer @Markus_J ! Using your code, I have been trying to color code each continuous variable, and to add a a scatter plot (stripchart function) overlaying the boxplots. But I haven´t been very successfully, I must say... My main problem is that the scatterplots are offset from the boxplots. Any suggestions? Thanks! – Teresa Aug 14 '23 at 09:29
  • @Teresa you are welcome. I have edited the code, so that the resulting graph better fits your description in the question. Hope this is what you want. Happy to help if you further specify what you hope to create... – Markus_J Aug 14 '23 at 10:45