Search code examples
rdistancespatialpatchterra

R terra calculate area moment of inertia OR how to get (weighted) raster-cell distance from patch-centroid


I'm trying to calculate a measure akin to the moment of inertia using a raster layer and I am struggling to figure out how to get the distance of each cell to a patch's centroid and then extracting both that distance and the cell's value.

I want to calculate the moment of inertia (get the squared distance of each cell to its patches centroid, multiply by value of cell, sum these values by patch, and then divide by the sum of all values per patch). I provide a simplified set-up below. The code creates a simple raster layer, patches clusters of cells, and gets their centroids. I know that the function in question to use next is probably terra::distance (maybe in combination with terra::zonal?!) -- how do I calculate the distance by patch?

#lonlat
library(terra)
r <- rast(ncols=36, nrows=18, crs="+proj=longlat +datum=WGS84")
r[498:500] <- 1
r[3:6] <- 1
r[111:116] <- 8
r[388:342] <- 1
r[345:349] <- 3


r_patched <- patches(r, directions = 8, allowGaps = F)
testvector <- terra::as.polygons(r_patched, trunc=T, dissolve = T)

p_centr <- geom(centroids(testvector), df=T)




##next steps

#1. get distance of each cell from patch's centroid
           #r <- distance(r)

#2. multiply cell value by squared distance to centroid



Solution

  • I think you need to loop over the patches. Something like this:

    p_centr <- centroids(testvector)
    v <- rep(NA, length(p_centr))
    for (i in 1:length(p_centr)) {
        x <- ifel(r_patched == p_centr$patches[i], i, NA)
        x <- trim(x)
        d <- distance(x, p_centr[i,])
        d <- mask(d, x)
        # square distance and multiply with cell values
        d <- d^2 * crop(r, d)
        v[i] <- global(d, "sum", na.rm=TRUE)[[1]]
    }
    
    v / sum(v)
    #[1] 1.213209e-05 1.324495e-02 9.864759e-01 2.669833e-04