2

Is it possible to conditionally subset (and summarize) a raster using another raster as an index?

I have a set of rasters that show monthly data across a number of years. For each point, I need to get the average of just part of the year (e.g., months 2-4). This is very simple using terra::tapp:

library(terra)

#sample data - only five layers for simplicity
s <- rast(nrow=4, ncol=3, nlyrs=5)
n <- ncell(s)
values(s[[1]]) <- sample(1:100, n, replace=T)
values(s[[2]]) <- sample(1:10, n, replace=T)
values(s[[3]]) <- sample(1:10, n, replace=T)
values(s[[4]]) <- sample(1:10, n, replace=T)
values(s[[5]]) <- sample(1:100, n, replace=T)

#take average across layers; separate average of first month from average of months 2-4
m <- tapp(s, index=c(1,2,2,2,1), fun=mean)

#second layer of output gives months 2-4
plot(m[[2]]) 

The complication is that the exact layers I need vary depending on the pixel. For example, for some pixels, I need to take layers 2-4, but for others I need layers 2-5.

I have a separate index raster (same size/resolution) that gives me, for each pixel, which layer I need to start with, and another that tells me which one I need to end with. Is there any way to conditionally apply the tapp index depending on the cell? Essentially, to create the index using a separate function?

So for the example below, I'd like to have half the cells use idx = c(1,2,2,2,2), while the other half would use idx = c(1,2,2,2,1).

#modify layer 5 to include two different cases of data
values(s[[5]]) <- c(sample(1:10, n/2, replace=T),
                    sample(1:100, n/2, replace=T))

#index of starting/ending values for the summary statistics
idx_start <- idx_end <- rast(nrow=4, ncol=3)
values(idx_start) <- rep(2, n)
values(idx_end) <- c(rep(4, n/2), rep(5, n/2))

# index for the first raster cell - I'd like this to be responsive across all raster cells
startval <- as.numeric(idx_start[1])
endval <- as.numeric(idx_end[1])
idx <- rep(1, dim(s)[3])
idx[startval:endval] <- 2
idx

#so I could do something like this
m2 <- tapp(s, idx, fun=mean)
1
  • If the which index to use is pixel valued, wouldn't this just be an if(? Certainly could be complex if else then, but limited. Commented Jan 29 at 19:51

1 Answer 1

2

You can use terra::rapp (the r stands for "range")

rapp(s, idx_start, idx_end, mean)

#class       : SpatRaster 
#dimensions  : 4, 3, 1  (nrow, ncol, nlyr)
#resolution  : 120, 45  (x, y)
#extent      : -180, 180, -90, 90  (xmin, xmax, ymin, ymax)
#coord. ref. : lon/lat WGS 84 (CRS84) (OGC:CRS84) 
#source(s)   : memory
#name        :      lyr1 
#min value   :  3.666667 
#max value   : 22.250000 
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.