rgisrasterterra

R terra equivalent of raster::overlay with a function of two rasters - slower with larger rasters?


I am looking to set the values of one raster to NA where they are NA in another raster. I have the code to do this using raster::overlay and a functional code block with terra as per below with rasters of two different sizes.

library(raster)
library(terra)
library(tictoc)

# small raster
r1 <- rast(system.file("ex/elev.tif", package="terra"))

# large raster
r1 <- rast(vals=runif(n=9e6,min=100,max=200),nrows = 3e3, ncols = 3e3, resolution = 0.5)

# second raster
r2 <- r1+100

# randomly set some values to NA in r1
r1[sample(x=seq(1,4000),size = 1000,replace=FALSE)] <- NA
terra::plot(r1,colNA='blue')

# set values of r2 to NA where r1 is NA using raster
tic()
rr <- raster::overlay(raster::raster(r1),raster::raster(r2),fun=function(r1,r2) {
  r2[is.na(r1[])] <- NA
  return(r2)
})
toc()

terra::plot(r1,colNA='blue')
terra::plot(rr,colNA='blue')

# same operation but with terra
rm(rr) # remove for fairness in memory allocation speeds
tic()
rr <- terra::app(x=c(r1,r2),fun=function(x) {
  x[2][is.na(x[1])] <- NA
  return(x[2])
})
toc()

In this example the terra version seems much faster than raster for the small raster (~0.03s to 0.4s). However, with a much larger raster, the opposite seems true (about 0.77s to 0.58s). Any ideas why that would be the case, and is there a more optimal way to code the terra code block? Thanks in advance.

Tried the code block as per above and would expect that the terra version is faster in all cases. However, it is slower with a much larger raster.


Solution

  • With your use of terra::app I get

    toc()
    #1.82 sec elapsed
    

    The much faster way to achieve this is to use terra::mask:

    tic(); rr <- mask(r2, r1); toc()
    #0.01 sec elapsed
    

    You can also speed up terra::app a lot by using a vectorized function:

    tic()
    rr <- terra::app(x=c(r1,r2), fun=function(x) {
      x[is.na(x[,1]), 2] <- NA
      return(x[,2])
    })
    toc()
    #0.12 sec elapsed