sf
sf copied to clipboard
Weighted centroids
Would it be good to have some sort of weighted centroid function? Ideally where you could group by another column? Something like the UID field in mean coordinates in QGIS.
spatialEco::wt.centroid() sort of does this, but doesn't allow you to group by a unique id. I have put this in to an sf version, but it doesn't group, which I was hoping to do. The use case I am thinking of is for population weighted centroids of one geographical area, weighted by the population of a smaller geographical area.
library(sf)
weighted_centroid <- function(x, weight){
if (!inherits(x, "sf"))
stop(deparse(substitute(x)), " must be a 'sf' object")
p <- x[[weight]]
Xw <- sum(st_coordinates(x)[, 1] * p)
Yw <- sum(st_coordinates(x)[, 2] * p)
wX <- Xw/sum(p)
wY <- Yw/sum(p)
df <- data.frame(wX = wX, wY = wY)
xy <- st_as_sf(df, coords = c("wX", "wY"))
return(xy)
}
# test using the example from https://www.rdocumentation.org/packages/spatialEco/versions/1.3-7/topics/wt.centroid
meuse_sf <- st_as_sf(meuse)
weighted_centroid(meuse_sf, 'zinc')
spatialEco::wt.centroid(meuse, 'zinc')
I think this a cool idea, but I think it would be confusing given the current behavior st_centroid which produces the centroid of each row. This is more akin to a summary function, like the ideal syntax would be something like
df %>%
group_by(gid) %>%
st_summarize(..., type = "weighted_centroid", weights = weight_column) %>%
ungroup()
But that's clearly a bigger kind of function because sf currently doesn't have st_summarize and is already extremely slow with normal summarize