Search code examples
rgisraster

What causes the difference between calc and cellStats in raster calculations in R?


I am working with a dataset that consists of 20 layers, stacked in a RasterBrick (originating from an array). I have looked into the sum of the layers, calculated with both 'calc' and 'cellStats'. I have used calc to calculate the sum of the total values and cellStats to look at the average of the values per layer (useful for a time series). However, when I sum the average of each layer, it is half the value of the other calculated sum. What causes this difference? What am I overlooking?

Code looks like this:

testarray <- runif(54214776,0,1) 
# Although testarray should contain a raster of 127x147 with 2904 time layers. 
# Not really sure how to create that yet. 

for (i in 1830:1849){
  slice<-array2[,,i]
  r <- raster(nrow=(127*5), ncol=(147*5), resolution =5, ext=ext1, vals=slice)
  x <- stack(x , r)
}

brickhp2 <- brick(x)

r_sumhp2 <- calc(brickhp2, sum, na.rm=TRUE)
r_sumhp2[r_sumhp2<= 0] <- NA


SWEavgpertimestepM <- cellStats(brickhp2, stat='mean', na.rm=TRUE)

The goal is to compare the sum of the layers calculated with 'calc(x, sum)' with the sum of the mean calculated with 'cellStats(x, mean)'.

Rasterbrick looks like this (600kb, GTiff) : http://www.filedropper.com/brickhp2 *If there is a better way to share this, please let me know.


Solution

  • The confusion comes as you are using calc which operates pixel-wise on a brick (i.e. performs the calculation on the 20 values at each pixel and returns a single raster layer) and cellStats which performs the calculation on each raster layer individually and returns a single values for each layer. You can see that the results are comparable if you use this code:

    library(raster)
    ##set seed so you get the same runif vals
    set.seed(999)
    
    ##create example rasters
    ls=list()
    for (i in 1:20){
      r <- raster(nrow=(127*5), ncol=(147*5), vals=runif(127*5*147*5))
      ls[[i]] <- r
    }
    ##create raster brick
    brickhp2 <- brick(ls)
    
    ##calc sum (pixel-wise)
    r_sumhp2 <- calc(brickhp2, sum, na.rm=TRUE)
    r_sumhp2 ##returns raster layer
    
    ##calc mean (layer-wise)
    r_meanhp2 <- cellStats(brickhp2, stat='mean', na.rm=TRUE)
    r_meanhp2 ##returns vector of length nlayers(brickhp2)
    
    ##to get equivalent values you need to divide r_sumhp2 by the number of layers 
    ##and then calculate the mean
    cellStats(r_sumhp2/nlayers(brickhp2),stat="mean")
    

    [1] 0.4999381

    ##and for r_meanhp2 you need to calculate the mean of the means
    mean(r_meanhp2)
    

    [1] 0.4999381

    You will need to determine for yourself if you want to use the pixel or layer wise result for your application.