Search code examples
rpackagecorrelationterra

Calculating pixelwise correlation between two multi-layer rasters in R with the terra package


Is there a function in the R terra package that is equivalent to the raster package's corLocal() syntax below

corLocal(x, y, method=c("spearman"), test=FALSE)

I'd like to calculate the pixelwise correlation between two multi-layer SpatRaster objects. The SpatRasters have the same extent, resolution, and number of layers. I also need to find the p-values for each pixel. I've found layerCor(), but it only takes in one SpatRaster as input.

Thanks


Solution

  • With terra 1.7-69 you can use xapp

    This currently is the development version of therra that you can install with:

    install.packages('terra', repos='https://rspatial.r-universe.dev')
    

    Example data

    library(terra)
    #terra 1.7.69
    r <- rast(ncols=10, nrows=10, nlyr=5)
    set.seed(1)
    r <- init(r, runif)
    s <- init(r, runif)
    

    Solution

    x <- xapp(r, s, fun=cor)
    #class       : SpatRaster 
    #dimensions  : 10, 10, 1  (nrow, ncol, nlyr)
    #resolution  : 36, 18  (x, y)
    #extent      : -180, 180, -90, 90  (xmin, xmax, ymin, ymax)
    #coord. ref. : lon/lat WGS 84 (CRS84) (OGC:CRS84) 
    #source(s)   : memory
    #name        :      lyr.1 
    #min value   : -0.9923990 
    #max value   :  0.9808943 
    

    Likewise, you can use cor.test, but you have to extract the value(s) you want from what that function returns. For example

    xtest <- xapp(r, s, fun=\(x, y) cor.test(x, y)$p.value)
    

    Unlike cor, cor.test fails when the input is NA. To work around this you can do

    naproof.cor.test <- function(x, y) {
        if (any(is.na(x)) || any(is.na(y))) return(NA)
        cor.test(x, y)$p.value
    }
    
    xtest <- xapp(r, s, naproof.cor.test)
    

    And you can get both the correlation coefficient and the p-value in one step like this

    my.cor <- function(x, y) {
        if (any(is.na(x)) || any(is.na(y))) return(c(NA, NA))
        unlist(cor.test(x, y)[c("estimate", "p.value")])
    }
    
    z <- xapp(r, s, my.cor)
    
    z
    #class       : SpatRaster 
    #dimensions  : 10, 10, 2  (nrow, ncol, nlyr)
    #resolution  : 36, 18  (x, y)
    #extent      : -180, 180, -90, 90  (xmin, xmax, ymin, ymax)
    #coord. ref. : lon/lat WGS 84 (CRS84) (OGC:CRS84) 
    #source(s)   : memory
    #names       : estimate.cor,      p.value 
    #min values  :   -0.9923990, 0.0007945862 
    #max values  :    0.9808943, 0.9992525680