Use 'project' function in {terra} raster package, treat NA as 0s

213 Views Asked by At

I'm trying to resample/project a high res raster, using a low res raster as a template

library("terra")

high_res <- rast(ncol = 2, nrow = 2, vals = c(1, NA, NA, NA))

low_res <- rast(nrow = 1, ncol = 1)

new_rast <- project(high_res, low_res, method = "average")

This works fine, but the value in the cell of the new rast is '1' as it has taken the average of all non-NA cells from the high_res raster.

Instead, I want it to treat NA values as 0. The result should be 0.25, not 1.

The method to do this must be memory-safe as I will be doing this on very large rasters (think 5m resolution covering a whole country).

Is there a clever way of doing this please?

2

There are 2 best solutions below

1
Gerald T On

You can simply replace NA values with 0s

library("terra")

high_res <- rast(ncol = 2, nrow = 2, vals = c(1, NA, NA, NA))

high_res[is.na(high_res)] <- 0

low_res <- rast(nrow = 1, ncol = 1)

new_rast <- project(high_res, low_res, method = "average")
4
Robert Hijmans On

As suggested by Gerald T, you can replace the NAs with zero. Here I show two approaches for that that are better (memory safe) than using the [<- replacement function.

library("terra")
high_res <- rast(ncol = 4, nrow = 2, vals = c(1, NA, NA, NA, NA, NA, NA, NA))
low_res <- rast(nrow = 1, ncol = 2)

high_zero <- subst(high_res, NA, 0)
# or 
# high_zero <- ifel(is.na(high_res), 0, high_res)

new_rast <- project(high_zero, low_res, method = "average")

Now to remove the zeros from cells that should be NA you would need to do

isna <- project(high_res, low_res, method = "average")
x <- mask(new_rast, isna)

Unless all values in high_res are positive such that if the sum is zero you know that all the contributing cells were NA. In that case you can do

x <- subst(new_rast, 0, NA)

(And with these example data, aggregate would be a more obvious method to use.)

new_rast <- aggregate(high_zero, 2, mean)