Search code examples
rfor-loopif-statementoverlayraster

Inconsistencies in error messages using a for loop and ifelse for raster overlay


Background -> I'm trying to remove all old forest out of certain forest types by using the overlay function. If the forest is type 1 and the age is > 250, then I want that cell to be 0, if it's type 2 and > 200 I want it to be 0, otherwise it can be what it is.

Problem -> I get two different error messages, with no consistency on which appears, and the code has produced correct results (once). The errors are:

#First error message
Error in setValues(x, value) : values must be a vector
Error in .local(x, i, j, ..., value) : cannot replace values on this raster (it is too large

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

I would like to know why it changes error messages (why it's inconsistent), and of course, what can I do to fix my code so that it works?

The code works when applied without a for loop, and has with it as well, but I can't reproduce the working result again.

My sample data and code:

library(raster)
library(dplyr)
set.seed(123)


r1 <- raster(ncol=100,nrow=100)
r2 <- raster(ncol=100,nrow=100)
r3 <- raster(ncol=100,nrow=100)
r4 <- raster(ncol=100,nrow=100)
r5 <- raster(ncol=100,nrow=100)

r1[] <- round(runif(n=ncell(r1), min=0, max = 1000))
r2[] <- round(runif(n=ncell(r1), min=0, max = 1000))
r3[] <- round(runif(n=ncell(r1), min=0, max = 1000))
r4[] <- round(runif(n=ncell(r1), min=0, max = 1000))
r5[] <- round(runif(n=ncell(r1), min=0, max = 1000))

testStack <- stack(x=c(r1,r2,r3,r4,r5))

testAge  <- raster(ncol=100,nrow=100)
testAge[]  <- round(runif(n=ncell(testAge), min=0,max=400))

testBec  <- raster(ncol=100,nrow=100)
testBec[]  <- round(runif(n=ncell(testBec), min = 1, max = 5))



testList <- list() # create a list to hold the files that will go into the raster stack

# create a for loop to run through raster stack and fill a list with the output rasters
for(i in 1:(nlayers(testStack))){
  testList[[i]] <- overlay(x=testStack, y=testBec, z=testAge, fun=function(x,y,z){ 
    ifelse(y == 1 & z > 249,    # if x is type 1 and z(age from inventory)
           0,                   # is >= 250, then y = 0, else      
           ifelse(y == 2 & z > 200,   # if x is type 2 and z is >200
                  0, x))        # y = 0, else keep x
    return(testList[[i]])       # return a list with rasters
  })
  testList[[i]] <- stack(testList[[i]])   
}

I'm running on a mac OS and RStudio Version 1.1.383, R 3.4.2 (2017-09-28)


Solution

  • To do this with the for loop:

    testList <- list() # create a list to hold the files that will go into the raster stack
    
    # create a for loop to run through raster stack and fill a list with the output rasters
    for(i in 1:(nlayers(testStack))){
      testList <- overlay(x=testStack[[i]], y=testBec, z=testAge, fun=function(x,y,z){ 
    
          temp <- ifelse(y == 1 & z > 249,0,       
                        ifelse(y == 2 & z > 200,0, x)) 
     return(temp)
    })
      tList[[i]] <- stack(testList)   
    }
    second_stack <- stack(tList)