Search code examples
rif-statementraster

Change cell value in one raster based on another raster


I have two raster maps from two points in time (t1 and t2) with two land-cover categories in each (LC1, LC2). I want impose a rule that a LC2-cell in t1 cannot change to LC1-cell in t2, i.e., only LC1 can change to LC2 through time but not the other way around. I am having a hard time coming up with a rule for that in R. What I had in mind was something like this:

#create test rasters
r <- raster(nrows=25, ncols=25, vals=round(rnorm(625, 3), 0)) #land-use/cover raster
r[ r > 2 ] <- 2
r[ r < 1 ] <- 1
r2 <- r
plot(r2) #r2 is t2

r <- raster(nrows=25, ncols=25, vals=round(rnorm(625, 3), 0)) #land-use/cover raster
r[ r > 2 ] <- 2
r[ r < 1 ] <- 1
plot(r) #r is t1

r_fix <- overlay(r, r2, fun = function(x, y) {
  if (x[ x==2 ] & y[ y==1 ]) { #1 is LC1, 2 is LC2
    x[ x==2 ] <- 1 }
  return(x)
})

But it returns an error (because of they way I am using the if statement with rasters?):

Error in (function (x, fun, filename = "", recycle = TRUE, forcefun = FALSE, : cannot use this formula, probably because it is not vectorized

I wonder if there is a simple way to implement something similar to that that works with rasters? Thank you in advance.


Solution

  • You were really close,

    overlay(r, r2, fun = function(x, y) {x[x == 2 & y == 1] <- 1; x})
    

    seems to do the job.

    In terms of your solution,

    x[x == 2] <- 1
    

    doesn't cause any errors, although it's not exactly what you want to use in your case either. However,

    if (x[x == 2] & y[y == 1])
    

    is a problem because x[x == 2] & y[y == 1] returns a matrix, while if wants just a single logical input. Subsetting, on the other hand, can handle logical matrices, which is exactly what is happening in x[x == 2 & y == 1].