[R] grid(Base): How to avoid "Figure region too small and/or viewport too large" by specifying 'relative' units?
Marius Hofert
marius.hofert at math.ethz.ch
Fri Oct 19 12:18:53 CEST 2012
Dear grid-expeRts,
The goal:
I would like to construct a plot (matrix) with grid and gridBase,
which consists of four "sub-plots". The sub-plots should have a square plotting
region as one would force with par(pty="s") in base graphics.
The problem:
I don't get a square plotting region, not even by specifying
pty="s" in par(). Indeed, if you display the grid layout by commenting in
"grid.show.layout(gl)" below, you'll see that the grid layout is fine, but the
plot does not seem to respect the layout measurements.
The initial quick-and-dirty hack:
Use absolute measurements, i.e., specify all
units in inches. This worked perfectly fine for me initially. However, when the
device width and height are not set accordingly (and one can never know what
others specify here -- indeed the problem arose this way), this produces errors
of type "Error in gridPLT() : Figure region too small and/or viewport too
large".
I also found this issue in this post
(https://stat.ethz.ch/pipermail/r-help/2008-December/181993.html), but I am
wondering what's the correct approach towards this problem / how can one specify
"relative" units but guarantee that the grid layout is respected when plotting
is done? [We use this plot in a quite complicated setup and the quick solution
to specify inches and a large enough width/height for the device fails.]
Cheers,
Marius
require(grid)
require(gridBase)
## setup
strg <- LETTERS[1:2] # row variables
t <- c(0.2, 0.8) # column variables
## plot variables (spaces)
pspc <- c(3,3)
spc <- c(0.3, 0.3)
axlabspc <- c(1.2, 0.75)
labspc <- c(0.3, 0.3)
## save plot settings
par. <- par(no.readonly=TRUE)
## set up the grid layout
nx <- 2 # number of sub-plots per column
nx. <- 5 # number of grid rectangles per column
ny <- 2 # number of sub-plots per row
ny. <- 5 # number of grid rectangles per row
plot.new() # start (empty) new page with 'graphics'
gl <- grid.layout(nx., ny., # "2 x 2" grid together with spaces => 5 x 5 grid
widths=c(axlabspc[1], rep(c(pspc[1], spc[1]), nx-1), pspc[1], labspc[1]),
heights=c(labspc[2], rep(c(pspc[2], spc[2]), ny-1), pspc[2], axlabspc[2]))
## grid.show.layout(gl) # display the layout; use this to see that the sub-plots do not match the layout specification
pushViewport(viewport(layout=gl)) # use this layout in a viewport
## generate dummy data to plot in the four sub-plots
n <- 10
x <- array(NA, dim=c(nx, ny, n))
for(i in 1:2) for(j in 1:2) x[i,j,] <- rep(i,n)+rep(j,n)+runif(n)
## go through the "panels"
set.seed(1)
for(i in 1:nx) { # rows
i. <- 2*i # column index in layout (for jumping over gaps)
yran <- range(x[i,,]) # for forcing the same y-axis within a row
for(j in 1:ny) { # columns
j. <- 2*j # row index in layout (for jumping over gaps)
pushViewport(viewport(layout.pos.row=i., layout.pos.col=j.))
## plot
par(plt=gridPLT()) # start a 'graphics' plot
par(new=TRUE) # always do this before each new 'graphics' plot
plot(range(1:n), yran, type="n", ann=FALSE, axes=FALSE) # set up coordinate axes
points(1:n, x[i,j,], type="b") # actual plot
grid.rect()
## axes
if(i==nx) axis(1) # x axis
if(j==1) axis(2) # y axes
upViewport()
## column labels
if(i==1){
pushViewport(viewport(layout.pos.row=1, layout.pos.col=j.))
grid.rect()
grid.text(t[j], x=0.5, y=0.5)
upViewport()
}
## row labels
if(j==2){
pushViewport(viewport(layout.pos.row=i., layout.pos.col=nx.))
grid.rect()
grid.text(strg[i], x=0.5, y=0.5, rot=-90)
upViewport()
}
}
}
## x axis label
pushViewport(viewport(layout.pos.row=ny., layout.pos.col=2:(ny.-1)))
grid.text(expression(gamma), y=unit(0.5, "null"))
upViewport()
## y axis label
pushViewport(viewport(layout.pos.row=2:(nx.-1), layout.pos.col=1))
grid.text(expression(f[gamma]), rot=90, x=unit(0.5, "null"))
upViewport()
## restore plot settings
par(par.)
More information about the R-help
mailing list