Home > other >  Set the space between subplots in R and draw a border for each one
Set the space between subplots in R and draw a border for each one

Time:09-01

I was really stuck in this for days! I have a loop that creates the different subplots. Finally, my plots are as follows. I have two problems with them: 1- could you please help me to set the space between them? 2- Honestly, I can not figure out how to set the values here also:

rect(grconvertX(0.025, 'ndc'), grconvertY(0.45, 'ndc'), grconvertX(0.5, 
        'ndc'), grconvertY(0.9, 'ndc'), xpd = NA)

Here is the figure I have, enter image description here

And here is the figure I want to make. enter image description here

my code dependet on multiple files and I can not provide a good example of that. However, the way that I create this figure is this:

for(i in 1:2){
 par(mar=c(4.5,4.5,10,4.5))
 m1 <- matrix(c(1, 2, 3, 4,5, 6, 7, 8), nrow = 2, ncol = 4, byrow = TRUE)
 layout(m1, widths = c(2.2, 1.6,2.2, 1.6))

   # A
    plotModelFit() #subplot 1 in A
    plotMarginal() #subplot 2 in A
    mtext("A", padj=0, adj=-2.6, cex=2.5, font=1)
    rect(grconvertX(0.025, 'ndc'), grconvertY(0.45, 'ndc'), grconvertX(0.5, 
    'ndc'), grconvertY(0.9, 'ndc'), xpd = NA) # this is for the box 
   #B 
 same as A 
 # C and D same as A
    dev.off()
}

Thank you so much

CodePudding user response:

This is how I would approach this. To have full control over empty space between the plots I like to set plot margins to zero and work with widths and heights of "non-plot" columns and rows of the layout (zeros in layout matrix) instead.

## define widths and heights
# outer margins
margin <- c(x=.07, y=.07)  
# widths: space left, subplot 1, middle space, subplot 2, space right
wd <- c(.3, 1, .3, .6, .05)
wd <- c(margin['x'], wd, wd, margin['x'])
wd <- wd / sum(wd)
# heights: space above, plot, space below
ht <- c(.2, 1, .4)
ht <- c(margin['y'], ht, ht, margin['y'])
ht <- ht / sum(ht)

## define layout matrix
row <- rep(c(0, 1, 0, 1, 0), 2)
mat <- rbind(0, 0, row, 0, 0, row, 0, 0)
mat <- cbind(0, mat, 0)
mat <- t(mat)
mat[mat==1] <- mat[mat==1]*seq_len(sum(mat))
mat <- t(mat)
#      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12]
# [1,]    0    0    0    0    0    0    0    0    0     0     0     0
# [2,]    0    0    0    0    0    0    0    0    0     0     0     0
# [3,]    0    0    1    0    2    0    0    3    0     4     0     0
# [4,]    0    0    0    0    0    0    0    0    0     0     0     0
# [5,]    0    0    0    0    0    0    0    0    0     0     0     0
# [6,]    0    0    5    0    6    0    0    7    0     8     0     0
# [7,]    0    0    0    0    0    0    0    0    0     0     0     0
# [8,]    0    0    0    0    0    0    0    0    0     0     0     0

You can see there are mostly zeros in the layout matrix. Nothing will be plotted in these cells but they allow you to better define empty space between plots. Specifying all relative widths and heights first also makes it easier to compute the coordinates for borders between/around plots drawn later with rect and lines.

par(mar=rep(0, 4))
layout(mat, widths=wd, heights=ht)

# plotting
for (i in 1:8) {
  plot(1)
  mtext('x axis label', side=1, line=2.5, cex=.8)
  mtext('y axis label', side=2, line=2.5, cex=.8)
  if (i %% 2) mtext(LETTERS[ceiling(i/2)], adj=-.3, line=.4, cex=1.5)
}

# drawing borders
rect.xy <- cbind(x=c(grconvertX(wd[1], 'ndc'),
                     grconvertX(sum(head(wd, -1)), 'ndc')),
                 y=c(grconvertY(tail(ht, 1), 'ndc'),
                     grconvertY(sum(head(ht, -1)), 'ndc')))
rect(rect.xy[1, 'x'], rect.xy[1, 'y'], 
     rect.xy[2, 'x'], rect.xy[2, 'y'], 
     xpd=NA)
lines(rect.xy[, 'x'], rep(mean(rect.xy[, 'y']), 2), xpd=NA)
lines(rep(mean(rect.xy[, 'x']), 2), rect.xy[, 'y'], xpd=NA)

Please note that it is necessary to redraw axis labels using mtext with xpd=NA. Plot layout with borders

  •  Tags:  
  • r
  • Related