rterra

What is the proper way to change the units of a raster to account for the area of each pixel using terra?


I have a raster for which I want to change the values to be pixel-value per hectar where the area comes from the size of the pixel. So if a pixel is 10 ha and its current value is 100 abitrary-units, now its going to be 10 abitrary-units/ha.

Example raster :

r <- rast(nrows=18, ncols=36)
v <- 1:ncell(r)
v[200:400] <- NA
values(r) <- v

This functions should take the raster and multiply by 1/ha.

px2ha <- function(raster) {
  raster * 10000/prod(res(raster))
}

What about using cellSize like this?

r2/cellSize(r2, unit = 'ha')

I don't get the same answer.

r2 = project(x = r, y = 'epsg:2950') # Put raster in meters 
plot((r2))
plot(px2ha(r2))
plot(r2/cellSize(r2, unit = 'ha'))

Could cellSize be used to get the pixel value per area (hectar)?


Solution

  • The correct thing to do is to use terra::cellSize. It should not matter whether your raster data is in lon/lat or not.

    library(terra)
    r <- rast(nrows=18, ncols=36)
    a <- cellSize(r, unit="ha")
    minmax(a)
    #         area
    #min  10803350
    #max 122787719
    

    Note the range of values because the cell size varies. This is also true after projection, but the numbers are not the same because a raster changes fundamentally with projection (and that is why you generally want to avoid that step).

    r2 <- project(r, "epsg:2950")
    b <- cellSize(r2, unit="ha")
    minmax(b)
    #         area
    #min   3535976
    #max 161759413
    

    There is no range in values of you use transform=FALSE

    d <- cellSize(r2, unit="ha", transform=FALSE)
    minmax(d)
    #         area
    #min 162812887
    #max 162812887
    

    Which is the same as (note that your formula for this was wrong)

    prod(res(r2)) / 10000
    #[1] 162812887
    

    But using this number is not correct because it assumes that there is no distortion. This number should be correct around coordinates (0,0) but the further you move away from there, the more distortion you get. cellSize corrects for that by transforming the cells back to lon/lat before computing the areas.

    In this example the distortion is huge, because a projection for a part of Canada is applied to the entire world. That is a bit unrealistic. Presumably, your actual data are only in Quebec and/or East Ontario and there the distortion would be much smaller.

    Older textbooks and classes may suggest you should project lon/lat data to a planar coordinate reference system to compute area, but that reflects the limitations of software that was used. It is not a good approach, in fact the opposite should be done.