I'm using the R package 'rastervis' to create a number of multi-plot figures. I'm continually running into alignment issues which I believe are the result of rounding in the plot legends. For example, a plot in which values are rounded to 3 decimal places will be shifted compared to those rounded to just two decimal places. Similarly, if two plots are rounded to 2 d.p. but one has minus values, this will also change the alignment of the plot (presumably because the '-' sign is taking up space within the plot).

I have attached an image of this misalignment and ask whether there is a simple argument which I haven't invoked which will fix the problem. After many search attempts I've been unable to find a solution. I've included some very low-tech red lines on this diagram to show how the plots are misaligned given legends with varying numbers of characters:

enter image description here

I would (ideally) like all plots to be left justified and to be the same width. This would hopefully align the legends too. All of the misalignment I'm experiencing really needs to be pushed to the whitespace on the right of the plot.

Here is a very quickly photo-shopped mock up of the intended result. Note how all plots and legends are aligned with any differences in whitespace given to the right of the plot window. I've done nothing to this image except shift the plots manually either left or right by a few pixels such that they align(i.e. I haven't resized the individual plots, I've just moved them slightly). enter image description here

Here is a minimum reproducible example. The misalignment isn't quite as severe as my real-world example shown in the images but it is still apparent.


r1 <- raster(nrow=18, ncol=36)
r1[] <- runif(ncell(r1)) * 10
r2 <- raster(nrow=18, ncol=36)
r2[] <- runif(ncell(r1)) * 2.345
r3 <- raster(nrow=18, ncol=36)
r3[] <- runif(ncell(r1)) * -4

p1 <- levelplot(r1, margin=FALSE, xlab=NULL, ylab=NULL,scales=list(draw=FALSE))
p2 <- levelplot(r2, margin=FALSE, xlab=NULL, ylab=NULL,scales=list(draw=FALSE))
p3 <- levelplot(r3, margin=FALSE, xlab=NULL, ylab=NULL,scales=list(draw=FALSE))

print(p,  split=c(1, 1, 1, 3), more=TRUE)
print(p2, split=c(1, 2, 1, 3), more=TRUE)
print(p3, split=c(1, 3, 1, 3))
  • its rasterVis with an upper-case V isn't it?
    – Spacedman
    Apr 16, 2018 at 17:31
  • Are you hitched to levelplot? Doing par(mfrow=c(3,1));plot(r1);plot(r2);plot(r3) gives you three aligned plots with individual colour schemes and legends.
    – Spacedman
    Apr 17, 2018 at 7:14
  • Thanks for the reply. I'm not hitched to rasterVis, no. I'm currently using it because it's easy to implement colourblind-safe palettes with this package. I've always found base raster graphics to be a bit of a faff!
    – Simon
    Apr 17, 2018 at 8:16
  • For plotting rasters with base plot, add col=somevectorofcolours, eg col=pals::plasma(10) (and install pals package, its ace).
    – Spacedman
    Apr 17, 2018 at 9:41

2 Answers 2


Steer the levelplot parameters at and colorkey. This solution is something of a workaround.

Fetch the minimum and maximum value across all your data, and perform floor / ceiling on these.

scaleMin <- floor(min(c(r1@data@values,r2@data@values,r3@data@values)))
scaleMax <- ceiling(max(c(r1@data@values,r2@data@values,r3@data@values)))

Set a number of desired breaks, and generate a sequence of universal breaks where effectively all values will be contained in your different levelplots.

numberOfBreaks <- 6
brksUniv <- seq(scaleMin,scaleMax, length.out=numberOfBreaks)

At this point a central step borrowed from the approach in this answer (Christopher Stephan 2017), is performed. Define at and colorkey. Finally, generate and print the plots with these information included.

myColorkey <- list(at=brksUniv, labels=list(at=brksUniv, labels=round(brksUniv,1)))
p1Univ <- levelplot(r1, margin=FALSE, xlab=NULL, ylab=NULL,scales=list(draw=FALSE), at=brksUniv, colorkey=myColorkey)
p2Univ <- levelplot(r2, margin=FALSE, xlab=NULL, ylab=NULL,scales=list(draw=FALSE), at=brksUniv, colorkey=myColorkey)
p3Univ <- levelplot(r3, margin=FALSE, xlab=NULL, ylab=NULL,scales=list(draw=FALSE), at=brksUniv, colorkey=myColorkey)

print(p1Univ, split=c(1, 1, 1, 3), more=TRUE)
print(p2Univ, split=c(1, 2, 1, 3), more=TRUE)
print(p3Univ, split=c(1, 3, 1, 3))

the resulting level plots with equal color scales

  • If you are going to do that you may as well do levelplot(stack(r1,r2,r3)). And if the data covers several orders of magnitude this won't work at all well.
    – Spacedman
    Apr 17, 2018 at 7:12
  • Thanks for the detailed reply. However the scale in my 'real' example spans two orders of magnitude; I do need different legends for each plot otherwise the top and middle plots will be unreadable compared to the middle plot.
    – Simon
    Apr 17, 2018 at 8:18

In case it is still relevant for you: I had the same problem recently and eventually solved it using the following workaround (which is a bit crude I admit, but it does the job): In the legend of each plot, I included an additional invisible label and set it to a high number (or some other long text). That way, R is forced to allocate the same amount of space for each legend and the plots are aligned.

To do this, you need to explicitly provide the ticks for the legends. Similar to the answer above, you can use

myColorbar1 <- seq(min(r1@data@values),max(r1@data@values),length.out=8)

or provide any other vector of legend ticks, and then use

p1 <- levelplot(r1, margin=FALSE, xlab=NULL, ylab=NULL,scales=list(draw=FALSE),
                colorkey = list(at=c(myColorbar1[1],myColorbar1),

and the same for the other plots (and of course, you can replace "1000000" by text of any other length if necessary). Unless your background is not white, the additional label won't be visible in the plot, and you can use a different legend for each of your plots.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.