I have three raster layers that I would to update based on certain conditions.
When the landcover is "anthropogenic", I would like to able to replace the values from the modified snowcover using the values from the input snowcover. I have been able to make this work as long as there are values in every single cell of all three raster files.
c[lc=='anthropogenic']<-b[lc=='anthropogenic']
However, when the raster includes cells without values (at the edges of the study area), it throws an error even though the extents match perfectly.
c[lc=='anthropogenic']<-b[lc=='anthropogenic']
#Error: [`[<-`] length of cells and values do not match
Here is some dummy code (rather silly) which reproduces the issue.
library(terra)
library(geodata)
#import world countries dataset
w <- world(path=".", resolution = 1)
#select three countries on coastline
sel<-w[w$NAME_0%in%c('Ghana', 'Togo', 'Benin'),]
#add dummy variable that is numeric (class would be equivalent)
sel$num<-c(1, 2, 3)
#import soil dataset
soil_full<-soil_af(var="pH", depth=15, path=".")
#crop to extent of three countries
soil<-crop(soil_full, ext(sel))
soil_dummy<-soil
#rasterize country dataset to same extent and resolution as soil dataset
values(soil_dummy)<-NA
sel_rast<-rasterize(x=sel, y=soil_dummy, field="num",
background=NA, update=TRUE, touches=TRUE)
names(sel_rast)<-"num"
par(mfrow=c(1,2))
plot(sel_rast)
plot(soil)
sel_rast[sel_rast==1]<-soil[sel_rast==1]
#Error: [`[<-`] length of cells and values do not match
sel_rast
#class : SpatRaster
#dimensions : 921, 853, 1 (nrow, ncol, nlyr)
#resolution : 0.008333333, 0.008333333 (x, y)
#extent : -3.258333, 3.85, 4.741667, 12.41667 (xmin, xmax, ymin, ymax)
#coord. ref. : lon/lat WGS 84 (EPSG:4326)
#source(s) : memory
#name : num
#min value : 1
#max value : 3
soil
#class : SpatRaster
#dimensions : 921, 853, 1 (nrow, ncol, nlyr)
#resolution : 0.008333333, 0.008333333 (x, y)
#extent : -3.258333, 3.85, 4.741667, 12.41667 (xmin, xmax, ymin, ymax)
#coord. ref. : lon/lat WGS 84 (EPSG:4326)
#source(s) : memory
#name : pH_5-15cm
#min value : 4.68
#max value : 7.85
#attempt with a mask
test<-mask(soil, sel_rast)
sel_rast[sel_rast==1]<-test[sel_rast==1]#fails
#crop to a subset within the landmass
sel_rast.c<-crop(sel_rast, ext(sel_rast)/10)
soil.c<-crop(soil, ext(sel_rast)/10)
plot(soil.c)
plot(sel_rast.c)
sel_rast.c[sel_rast.c==3]<-soil.c[sel_rast.c==3]#works
plot(sel_rast.c)
Related questions but do not deal with the specific issue: Conditional update without holes Conditionally update rast values from another raster using terra Compares a raster with a polygon but it needs to be all rasters for my actual analysis Extracting values from one raster based on condition in another raster and distinguished by polygons in a vector file
Minimal example data
library(terra)
lc <- rast(ncol=4, nrow=5)
lc <- init(lc, "col")
snow <- init(lc, "row")
modsnow <- init(lc, "cell")
You can use terra::ifel
d <- ifel(lc == 2, modsnow, snow)
Under the hood, this uses a combination of terra::cover
, terra::mask
and terra::classify
You can also use terra::lapp
f <- function(x, y, z) {
i <- which(x==2)
y[i] <- z[i]
y
}
x <- lapp(c(lc, snow, modsnow), f)