Search code examples
rgeospatialgeosphere

Calculate a centre point of multiple lat, long points in a data-frame


I have a dataset that looks like this:

site   lat      long 
bras2  41.21   -115.11
tex4   45.3    -112.31
bras2  41.15   -115.15 
bras2  41.12   -115.19

For samples with the same site name, I want to calculate their centre point and then add it as a column to the dataset. Some site names are duplicated twice, other three times, other four times.

Like this:

site   lat      long    centre_lat  centre_long 
bras2  41.21   -115.11  value here     value here
tex4   45.3    -112.31  45.3           -112.31 
bras2  41.15   -115.15  value here     value here
bras2  41.12   -115.19  value here     value here

How can I do this?


Solution

  • If you're using spatial data, you should look into using the sf package. It handles geometries and functions for operating on them well.

    Code below shows using both sf::st_centroid and geosphere::centroid. I prefer sf's way of doing things.

    df <- read.table(header=TRUE, text= "site   lat      long 
    bras2  41.21   -115.11
    tex4   45.3    -112.31
    bras2  41.15   -115.15 
    bras2  41.12   -115.19")
    
    
    library(dplyr)
    library(geosphere)
    library(sf)
    
    # Using sf's st_centroid
    df_sf <- st_as_sf(df, coords = c('long', 'lat'))
    
    centroids_sf <- df_sf %>%
      group_by(site) %>% 
      summarize(geometry = st_union(geometry)) %>% 
      st_centroid
    
      
    # Using geosphere::centroid
    centroids_geoshpere <- df_sf %>%
      group_by(site) %>%
      filter(n() >2)  %>% ## geosphere needs polygons therefore 3+ points
      st_union() %>%
      st_cast('POLYGON') %>%
      as('Spatial') %>% # geoshpere expects SpatialPolygons objects
      centroid() 
      
    
    centroids_geoshpere
    #>         [,1]     [,2]
    #> [1,] -115.15 41.16001
    centroids_sf
    #> Simple feature collection with 2 features and 1 field
    #> geometry type:  POINT
    #> dimension:      XY
    #> bbox:           xmin: -115.15 ymin: 41.16 xmax: -112.31 ymax: 45.3
    #> CRS:            NA
    #> # A tibble: 2 x 2
    #>   site         geometry
    #> * <chr>         <POINT>
    #> 1 bras2 (-115.15 41.16)
    #> 2 tex4   (-112.31 45.3)
    

    Looks like thery're close enough to the same point. I don't think geosphere::centroid can give a centroid for a single point, but may be wrong. sf::st_centroid has no problem with 1,2, or more points. Created on 2020-12-20 by the reprex package (v0.3.0)