Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Allocating equal plot space to all of multiple plots with shared axes

Tags:

plot

r

I'm trying to tile plots, specifically in a 2x3 matrix, for example:

x <- seq(1, 10, by=.01)
y <- 1/x

prms<-
  list(xlab=rep(c("", "x"), each=3),
       ylab=rep(c("y", "", ""), 2),
       xaxt=rep(c("n", "s"), each=3),
       yaxt=rep(c("s", "n", "n"), 2),
       mar=list(c(0  , 4.1, 4.1,   0),
                c(0  ,   0, 4.1,   0),
                c(0  ,   0, 4.1, 1.1),
                c(5.1, 4.1,   0,   0),
                c(5.1,   0,   0,   0),
                c(5.1,   0,   0, 1.1)))

par(mfrow=c(2, 3))
for (ii in 1:6){
  par(mar=prms$mar[[ii]])
  plot(x, y, type="l", lwd=2,
       xlab=prms$xlab[ii], ylab=prms$lab[ii],
       xaxt=prms$xaxt[ii], yaxt=prms$yaxt[ii])
}

Which produces:

A plot suffering from the problem described. The plot is a 2x3 panel of the same "l" curve repeated. The intention is for all 6 plots to occupy roughly the same "visual real estate", but in this output, the first column is "squeezed" and the 2nd column takes the plurality of space.

I've suppressed the "inner" margins and axes because all x (resp., y) units are the same, so such axes would be redundant. However, as you can see, by squeezing the margins on the left- and rightmost plots, I've accidentally given the middle plots too much space (it's not as apparent, but the same trouble plagues the top vis-a-vis the bottom row).

Therein lies the conundrum. mfrow assigns equal space to each subplot (i.e., axes, margins, etc), not to each plot area. How can I change my approach so that each plotting area is of equal size, ceteris paribus (i.e., axes, etc. unchanged)? I thought of using layout, but couldn't think of a nice programmatic way to go about making sure everything has equal representation.

like image 472
MichaelChirico Avatar asked Aug 18 '15 03:08

MichaelChirico


1 Answers

You may set mar to 0, and use oma to give the size of the outer margins. Axes are added to relevant plots in a loop. Common x and y axis labels are added with mtext and outer = TRUE

par(mfrow = c(2, 3),
    mar = c(0, 0, 0, 0),
    oma = c(4, 4, 0.5, 0.5))

for (i in 1:6) {
  plot(x, y, type = "l", axes = FALSE)
  if (i %in% c(4, 5, 6))
    axis(side = 1)
  if (i %in% c(1, 4))
    axis(side = 2)
  box()
  }

mtext("x values", side = 1, outer = TRUE, line = 2.5)
mtext("y values", side = 2, outer = TRUE, line = 2.5)

enter image description here

See also How to create multiple plots, each with same plot area size, when only one plot has axis labels?

like image 128
Henrik Avatar answered Oct 18 '22 11:10

Henrik