0

I want to multiply two rasters (one has 25 images, and the second raster has 1 image). I am using the loop function for multiplication. But I am not getting the results.

library(raster)
library(rgdal)

x = raster("D:/MODIS/img.tif") # 25images
y = raster("D:/urban.tif")     # 1 image
z <- function(x,y){x*y}

beginCluster(25) # your availables cores
for (i in 1:length(x)) {
  ndvi <- (x[[i]])
  urban <- (y)
  ndvi_urban <- clusterR(stack(ndvi,urban), calc, args = list(fun = z))
  writeRaster(ndvi_urban,output_name[i])
} 
endCluster()
1
  • Using terra you can simply use prod(c(ndvi,urban), na.rm=TRUE) however the rasters need to be SpatRasters objects read or coerced using terra::rast Commented Apr 7, 2023 at 0:35

2 Answers 2

1

You can use sapply in combination with lapp ({terra} package, since it's faster than {raster}):

sapply(1:25, function(X) lapp(c(x[[X]],y), function(x,y){x*y}))

Por parallelization, you can use cores argument:

library(parallel)
n = detectCores()
sapply(1:25, function(X) lapp(c(x[[X]],y), function(x,y){x*y}, cores = n))

You can even export each result:

sapply(1:25, function(X) lapp(c(x[[X]],y), function(x,y){x*y}, filename = paste0('path/to/file', X, '.tif')))

Reproducible example:

library(terra)

set.seed(123)

x = rast()
y = rast()

x = rast(sapply(1:25, function(X){setValues(x,rnorm(ncell(x)))}))
y = setValues(y,rnorm(ncell(y)))
  
print(x)
# class       : SpatRaster 
# dimensions  : 180, 360, 25  (nrow, ncol, nlyr)
# resolution  : 1, 1  (x, y)
# extent      : -180, 180, -90, 90  (xmin, xmax, ymin, ymax)
# coord. ref. : lon/lat WGS 84 
# source(s)   : memory
# names       :     lyr.1,     lyr.1,     lyr.1,    lyr.1,     lyr.1,     lyr.1, ... 
# min values  : -4.129135, -4.382098, -4.289319, -4.23503, -4.132421, -4.351687, ... 
# max values  :  4.322815,  4.206090,  4.124220,  4.52151,  4.599884,  4.759086, ... 

print(y)
# class       : SpatRaster 
# dimensions  : 180, 360, 1  (nrow, ncol, nlyr)
# resolution  : 1, 1  (x, y)
# extent      : -180, 180, -90, 90  (xmin, xmax, ymin, ymax)
# coord. ref. : lon/lat WGS 84 
# source(s)   : memory
# name        :     lyr.1 
# min value   : -3.985896 
# max value   :  4.165254 

rast(sapply(1:25, function(X) lapp(c(x[[X]],y), function(x,y){x*y})))
# class       : SpatRaster 
# dimensions  : 180, 360, 25  (nrow, ncol, nlyr)
# resolution  : 1, 1  (x, y)
# extent      : -180, 180, -90, 90  (xmin, xmax, ymin, ymax)
# coord. ref. : lon/lat WGS 84 
# source(s)   : memory
# names       :      lyr1,       lyr1,      lyr1,      lyr1,      lyr1,      lyr1, ... 
# min values  : -7.865725, -12.337091, -9.967996, -8.919808, -9.330696, -9.985127, ... 
# max values  :  7.787720,   9.870736, 11.646272,  9.325943, 10.125534, 10.062626, ... 
5
  • Thank you so much for your reply. However, I am getting this error "Error in (function (classes, fdef, mtable) : unable to find an inherited method for function ‘lapp’ for signature ‘"list")
    – user221527
    Commented Apr 6, 2023 at 19:17
  • Load the raster file with rast("D:/MODIS/img.tif"). Switch your entire analysis to {terra}, most functions are the same and the improvement is huge
    – aldo_tapia
    Commented Apr 6, 2023 at 19:52
  • I tried, but it is showing the same error.
    – user221527
    Commented Apr 6, 2023 at 20:15
  • I added a reproducible example using a raster with 25 layers, check steps, inputs, and outputs. Probably you are using a list with 25 rasters, rast() should fix that
    – aldo_tapia
    Commented Apr 6, 2023 at 20:33
  • Thank u for the explanation. It is working now.
    – user221527
    Commented Apr 6, 2023 at 21:40
1

In R, shorter objects are recycled to match longer objects, so you can directly multiply the two rasters.

library(terra)
x <- rast("D:/MODIS/img.tif") # 25images
y <- rast("D:/urban.tif")     # 1 image
z <- x * y

With some example data

library(terra)
x <- rast(ncol=10, nrow=10, nlyr=25, vals=1:2500)
y <- rast(ncol=10, nrow=10, nlyr=1, vals=1:100)
z <- x * y

z
#class       : SpatRaster 
#dimensions  : 10, 10, 25  (nrow, ncol, nlyr)
#resolution  : 36, 18  (x, y)
#extent      : -180, 180, -90, 90  (xmin, xmax, ymin, ymax)
#coord. ref. : lon/lat WGS 84 
#source(s)   : memory
#names       : lyr.1, lyr.2, lyr.3, lyr.4, lyr.5, lyr.6, ... 
#min values  :     1,   101,   201,   301,   401,   501, ... 
#max values  : 10000, 20000, 30000, 40000, 50000, 60000, ... 

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.