mo-seph
mo-seph

Reputation: 6223

How can I create raster plots with the same colour scale in R

I'm creating some maps from raster files using the "raster" package in R. I'd like to create comparison rasters, showing several maps side by side. It's important for this that the colour scales used are the same for all maps, regardless of the values in each map. For example, if map 1 has values from 0-1, and map 2 has values from 0-0.5, cells with a value of 0.5 should have the same colour on both maps.

For example:

I would like a value of 0.5 to have the same colour in both maps (i.e. yellow, as halfway between red and green). The current behaviour is that it is yellow in map 1, and green in map 2.

I can't find a way to make this work. I can't see any way to set the range of pixel values to use with the plotting function. setMinMax() doesn't help (as 'plot' always calculates the values). Even trying to set the values by hand (e.g. g1@data@max <- 10) doesn't work (these are ignored when plotting).

Finally, making a stack of the maps (which might be expected to plot everything on the same colour scale) doesn't work either - each map still has it's own colour scale.

Any thoughts on how to do this?

EDIT:

The solution I ended up using is:

plot( d, col=rev( rainbow( 99, start=0,end=1 ) ), breaks=seq(min(minValue( d )),max(maxValue(d)),length.out=100) ) 

Upvotes: 24

Views: 25465

Answers (7)

CARLOS_BEDSON
CARLOS_BEDSON

Reputation: 53

Try rasterVis::levelplot(x) where x is a stack of your raster files

Upvotes: 0

Adam Clark
Adam Clark

Reputation: 86

A pretty simple solution that should usually work (e.g. with the "plot" function in the raster package) is to set "z axis" limits (which control the colors and the color legend).

E.g. you can do something like: plot(d, zlim=c(0,1))

where d is a stacked raster object. Or, if you have a bunch of separate rasters d1, d2, d2..., you can just do: plot(d1, zlim=c(0,1)) plot(d2, zlim=c(0,1)) plot(d3, zlim=c(0,1)) ...

Upvotes: 1

It did not work for me. I used this script to split the color scale and select the one more suitable according to my data:

plot(d, col=rev(heat.colors(8, alpha = 1)), breaks = seq(0, 0.40, by = 0.05))

Upvotes: 1

glaroc
glaroc

Reputation: 463

Easy solution now is to use the zlim option.

plot( d, col=rev( rainbow( 99, start=0,end=1 ) ),zlim=c(0,1) )

Upvotes: 18

mo-seph
mo-seph

Reputation: 6223

Added as an answer in response to @Tomas

The answer I ended up using is:

plot( d, col=rev( rainbow( 99, start=0,end=1 ) ), 
    breaks=seq(min(minValue( d )),max(maxValue(d)),length.out=100) ) 

Upvotes: 6

rrrrrh
rrrrrh

Reputation: 41

There is more work to be done here in 'raster' but here is a hack:

 library(raster)
 r1 <- r2 <- r3 <- raster(ncol=10, nrow=10)
 r1[] <- runif(ncell(r1))
 r2[] <- runif(ncell(r2)) / 2
 r3[] <- runif(ncell(r3)) * 1.5
 r3 <- min(r3, 1)
 s <- stack(r1, r2, r3)


 brk <- c(0, 0.25, 0.5, 0.75, 1)
 par(mfrow=c(1,3))
 plot(r1, breaks=brk, col=rainbow(4), legend=F)
 plot(r1, breaks=brk, col=rainbow(4), legend.only=T, box=F)
 plot(r2, breaks=brk, col=rainbow(4), legend=F)
 plot(r1, breaks=brk, col=rainbow(4), legend.only=T, box=F)
 plot(r3, breaks=brk, col=rainbow(4), legend=F)
 plot(r1, breaks=brk, col=rainbow(4), legend.only=T, box=F)

You can also use the spplot function (sp package)

 s <- stack(r1, r2, r3) 
 sp <- as(s, 'SpatialGridDataFrame')
 spplot(sp)

You can also send the values to ggplot (search the r-sig-geo archives for examples) If your RasterLayer links to a very large file, you might first do, before going to ggplot

r <- sampleRegular(r, size=100000, asRaster=TRUE) 

and then perhaps

m <- as.matrix(r)

Upvotes: 4

IRTFM
IRTFM

Reputation: 263332

Since the image::raster function specifies that the image::base arguments can be passed (and suggests that image::base is probably used), wouldn't you just specify the same col= and breaks= arguments to all calls to image::raster? You do need to get the breaks and the col arguments "in sync". The number of colors needs to be one less than the number of breaks. The example below is based on the classic volcano data and the second version shows how a range of values can be excluded from an image:

 x <- 10*(1:nrow(volcano))
 y <- 10*(1:ncol(volcano))
 image(x, y, volcano, col = terrain.colors( length(seq(90, 200, by = 5))-1), axes = FALSE, breaks= seq(90, 200, by = 5) )
 axis(1, at = seq(100, 800, by = 100))
 axis(2, at = seq(100, 600, by = 100))
 box()
 title(main = "Maunga Whau Volcano", font.main = 4)



 x <- 10*(1:nrow(volcano))
 y <- 10*(1:ncol(volcano))
 image(x, y, volcano, col = terrain.colors( length(seq(150, 200, by = 5))-1), axes = FALSE, breaks= seq(150, 200, by = 5) )
 axis(1, at = seq(100, 800, by = 100))
 axis(2, at = seq(100, 600, by = 100))
 box()
 title(main = "Maunga Whau Volcano Restricted to elevations above 150", font.main = 4)

A specific example would aid this effort.

Upvotes: 12

Related Questions