0
votes

I have a problem with the "stackApply" function from the raster-package. First I want to stack three raster layers (each layer has one band) - that works. And then I want to create a raster-object that shows in which of the three bands/layers the minimum value occurs (each pixel in the raster layers has a different value). But I get various error messages. Does anyone have an idea how I can solve the problem? Thank you

stacktest<-stack(test,test1,test2)
min_which <- stackApply(stacktest, indices=1, fun=function(x, na.rm=NULL)which.min(x))

Error in setValues(out, v) : values must be a vector
Error in is.infinite(v) : not implemented standard method for type 'list'
1

1 Answers

1
votes

Here is a minimal, self-contained, reproducible example:

Example data from ?stackApply

library(raster)
r <- raster(ncol=10, nrow=10)
values(r) <- 1:ncell(r)
s <- stack(r,r,r,r,r,r)
s <- s * 1:6

Now use these data with your function (I removed the na.rm=NULL as it is not used)

w <- stackApply(s, indices=1, fun=function(x, ...) which.min(x) )
w
#class      : RasterLayer 
#dimensions : 10, 10, 100  (nrow, ncol, ncell)
#resolution : 36, 18  (x, y)
#extent     : -180, 180, -90, 90  (xmin, xmax, ymin, ymax)
#crs        : +proj=longlat +datum=WGS84 +no_defs 
#source     : memory
#names      : index_1 
#values     : 1, 1  (min, max)

Same for which.max

w <- stackApply(s, indices=1, fun=function(x, na.rm=NULL) which.max(x) )
w
# (...)
#values     : 6, 6  (min, max)

This suggest it works fine. In most cases that means that you probably have cells that are NA

s[1:10] <- NA
w <- stackApply(s, indices=1, fun=function(x, ...) which.min(x) )
# Error in setValues(out, v) : values must be numeric, logical or factor

It is easy to see why this error occurs

which.min(3:1) 
#[1] 3
which.min(c(3:1, NA))
#[1] 3
which.min(c(NA, NA, NA))
#integer(0)

If all values are NA, which.min does not return NA as expected. Instead it returns an empty vector. That can be fixed like this

which.min(c(NA, NA, NA))[1]
#[1] NA

And you can do

w <- stackApply(s, indices=1, fun=function(x, ...) which.min(x)[1] )

However, using stackApply with indices=1 is not a good approach. You should generally use calc to compute cell values across all layers.

y <- calc(s, function(x) which.min(x)[1])

But in this case you can use the more straightforward

z <- which.min(s)