Search code examples
rrasterterra

Use of weights and exact argument for estimating weighted mean from a raster using a polygon


I am trying to understand the difference between exact and weights argument in the extract function in terra package. My ultimate goal is to do a weighted average of raster within a polygon

library(terra)

f <- system.file("ex/lux.shp", package="terra")
v <- vect(f)
v <- v[1:2,]
z <- rast(v, resolution=.1, names="test")
values(z) <- 1:ncell(z)
rf <- system.file("ex/elev.tif", package="terra")
x <- rast(rf)

head(terra::extract(x, v, weight = T, touches = T))
  
ID elevation weight
1  1        NA   0.08
2  1        NA   0.17
3  1       529   0.30
4  1       542   0.52
5  1       547   0.74
6  1       535   0.18
  
head(terra::extract(x, v, exact = T, touches = T))
ID elevation   fraction
1  1        NA 0.03471857
2  1        NA 0.11553771
3  1       529 0.23902885
4  1       542 0.45706171
5  1       547 0.68120503
6  1       535 0.12033581
 

Why the weight and fraction are different in both cases? When I try to compute the weighted mean:

terra::extract(x, v, fun = mean, weights = T, touches = T, na.rm = T)
ID elevation
1  1       NaN
2  2       NaN
  
terra::extract(x, v, fun = mean, exact = T, touches = T, na.rm = T)
ID elevation
1  1  467.3792
2  2  334.6856
  

Why does the first gives me NaN while the 2nd gives me some values. If I calculate it manually, I can see the weighted mean is what the exact = T is giving me so what is the use of weights argument?

test_df <- terra::extract(x, v, exact = T, touches = T, na.rm = T)
test_df %>%
  dplyr::group_by(ID) %>%
  dplyr::summarise(wt_mean = weighted.mean(elevation, fraction, na.rm = T))
  
ID wt_mean
1    467.
2    335.
  
  

Solution

  • In my version of "terra" the results are very similar.

    library(terra)
    #terra 1.6.53
    
    f <- system.file("ex/lux.shp", package="terra")
    v <- vect(f)
    v <- v[1:2,]
    z <- rast(v, resolution=.1, names="test")
    values(z) <- 1:ncell(z)
    rf <- system.file("ex/elev.tif", package="terra")
    x <- rast(rf)
    
    terra::extract(x, v, fun = mean, weights = T, touches = T, na.rm = T)
    #  ID elevation
    #1  1  467.3934
    #2  2  334.6551
    terra::extract(x, v, fun = mean, exact = T, touches = T, na.rm = T)
    #  ID elevation
    #1  1  467.3792
    #2  2  334.6856
    

    The documentation says that with "weights", "the approximate fraction of each cell" is used whereas with "exact", "the exact fraction" is used.

    The reason for having both is in part because the argument "weights" predates the argument "exact". "weights" was kept because it could be faster and close enough in most cases.

    P.S., you can also do

    exactextractr::exact_extract(x, st_as_sf(v), "mean")
    #[1] 467.3792 334.6855