Return centroid of points using st_centroid

843 Views Asked by At

I'm after the centroid of a group of points. I expected st_centroid to return the centroid, but it appears to just return the original set of points. It seems the solution to this should be easy to find, but cannot find answer in a good hunt around stack overflow.

How can I get st_centroid to return the centroid - therefore a single point in the centre of a cluster of points.

library(dplyr)
library(sf)

df <- read.table(header=TRUE, text= "site   lat      long 
site1  41.21   -115.11
site2   45.3    -112.31
site3  41.15   -115.15 
site4  41.12   -115.19")

df_sf <- st_as_sf(df, coords = c('long', 'lat'))

st_centroid(df_sf)
2

There are 2 best solutions below

0
Jindra Lacko On BEST ANSWER

Are you after 1 centroid of your whole dataset?

If so, consider combining all your points to one feature using a sf::st_combine() call before calculating the centroid.

Because an example is more than words:

library(dplyr)
library(sf)

df <- read.table(header=TRUE, text= "site   lat      long 
site1  41.21   -115.11
site2   45.3    -112.31
site3  41.15   -115.15 
site4  41.12   -115.19")

df_sf <- st_as_sf(df, coords = c('long', 'lat'))

st_centroid(df_sf) # your original code; not quite what we want...
# Simple feature collection with 4 features and 1 field
# Geometry type: POINT
# Dimension:     XY
# Bounding box:  xmin: -115.19 ymin: 41.12 xmax: -112.31 ymax: 45.3
# CRS:           NA
#    site              geometry
# 1 site1 POINT (-115.11 41.21)
# 2 site2  POINT (-112.31 45.3)
# 3 site3 POINT (-115.15 41.15)
# 4 site4 POINT (-115.19 41.12)

df_mod <- df_sf %>% 
  st_combine()

st_centroid(df_mod) # would this fit your expectations better?
# Geometry set for 1 feature 
# Geometry type: POINT
# Dimension:     XY
# Bounding box:  xmin: -114.44 ymin: 42.195 xmax: -114.44 ymax: 42.195
# CRS:           NA
# POINT (-114.44 42.195)
2
DaveArmstrong On

I think the problem is that it assumes each coordinate pair is a different geometry and is trying to find the centroid of each point, which is just that point. What if you treated the entire set of points as a single multi-point geometry:

library(dplyr)
library(sf)
library(sfheaders)


df <- read.table(header=TRUE, text= "site   lat      long 
site1  41.21   -115.11
site2   45.3    -112.31
site3  41.15   -115.15 
site4  41.12   -115.19")

sf_multipoint(df[,c("long", "lat")]) %>% 
  st_centroid()
#> Simple feature collection with 1 feature and 1 field
#> Geometry type: POINT
#> Dimension:     XY
#> Bounding box:  xmin: -114.44 ymin: 42.195 xmax: -114.44 ymax: 42.195
#> CRS:           NA
#>   id               geometry
#> 1  1 POINT (-114.44 42.195)

To just return the coordinate values of the centroid, you could do the following:

sf_multipoint(df[,c("long", "lat")]) %>% 
  st_centroid() %>%
  st_coordinates()
#>         X      Y
#> 1 -114.44 42.195

Created on 2023-03-31 with reprex v2.0.2