# How to crop raster in R without losing the colors?

I have a 2x3 raster in R, with values 1 to 6.

library(raster)
r <- raster(nrows=3,ncols=2,xmn=0,xmx=2,ymn=0,ymx=3,vals=1:6)
colors <- c('red','orange','yellow','green','blue','purple')
plot(r,col=colors)

Now if I clip the raster, leaving the first two values out (red and orange), the color palette becomes useless.

r1 <- crop(r,extent(c(0.5,1.5,0.5,1.5)))
plot(r1,col=colors)

Notice how the extent includes only the colors yellow, green, blue and purple from the first picture. However, these are not the colors in the second picture. The numbers in the raster are correct.

> values(r)
[1] 1 2 3 4 5 6
> values(r1)
[1] 3 4 5 6

How can I use the same color variable (colors) in both cases in a consistent way?

My real world problem is cropping a world raster into country maps, using the same vegetation color code.

• In the first plot you have an implicit range (zlim) of c(1, 6), so you can get the same result with plot(crop(r,extent(c(0.5,1.5,0.5,1.5))), col = colors, zlim = c(1,6)). Whether that will work with other palette choices is unclear though, you can control more specifically with the breaks argument. – mdsumner Jun 25 '19 at 1:06
• You neeid to look at categorical rasters for mapping when your are representing discrete categories of data rather than possibly continuous numeric values. See help(raster::ratify) – Spacedman Jun 25 '19 at 6:36
• @Spacedman My raster is categorical, with 23 levels. It's the GLC2000 (Global Land Cover) project. – Rodrigo Jun 26 '19 at 1:15
• @mdsumner Thank you, zlim apparently solved my problem. – Rodrigo Jun 26 '19 at 1:16
• The raster you construct in the example has integers in it but R doesn't know it represents categorical data. The raster package supports properly categorical rasters with colour palette information. – Spacedman Jun 26 '19 at 8:08

Building from what @Spacedman said in comments, try ratifying the raster (have a look here and here) and then using levelplot (here and here)

r <- raster(nrows=3,ncols=2,xmn=0,xmx=2,ymn=0,ymx=3,vals=1:6)

# ratify it, set a new colours attribute and put back into the raster
r <- ratify(r)
rat <- levels(r)[[1]]
rat\$cols <- c('red','orange','yellow','green','blue','purple')
levels(r) <- rat

# levelplot
levelplot(r,col.regions=levels(r)[[1]]\$cols)

# now crop the ratified raster
r1 <- crop(r,extent(c(0.5,1.5,0.5,1.5)))

# looking at the raster will reveal and value range of 3 to 6 but an
# attribute table including all original values & associated colours

# plot
levelplot(r1,col.regions=levels(r1)[[1]]\$cols)

fiddling around with levelplot options etc will give you the correct legend