使用 sf 调整质心空间多边形

Adjust centroids spatial polygons using sf

我有一个地方政府区域的 shapefile。我使用 sf_read() 将其作为 SF 对象导入到 R 中。我想计算地方政府区域之间的距离。 st_centroid() 给我多边形质心,我可以使用 st_distance().

计算距离
regions <- st_read("~/Downloads/regions.shp")

regions_with_centroids <- st_centroid(regions)

extract_centroids <- regions_with_centroids %>% 
                           st_drop_geometry() %>% 
                           as_tibble() %>%
                           select(region_name, centroid)
# create edge list

edge_list <- extract_centroids %>%
                           select(region_name) %>%
                           expand(from = region_name, to = region_name) %>% 
                           filter(from < to) %>%
                           left_join(extract-centroids, by = c("from" = "region_name) %>%
                           rename(from_centroid = centroid) %>%
                           left_join(extract-centroids, by = c("to" = "region_name) %>%
                           rename(to_centroid = centroid) %>%
                           mutate(distance = st_distance(from_centroid, to_centroid)

不过,我很想分析一下各政府辖区内主要城区之间的通勤距离。我需要将质心转移到人口“重心”。

我可以使用人口普查普查员区域的 shapefile 来帮助我解决这个问题。普查员区域的大小按人口计算。使用 st_intersection() 我可以将普查员区域与政府区域相交。这为我提供了每个政府区域内的子区域。我可以计算所有子区域的质心。按区域分组,我可以计算一个区域中所有子区域的平均质心。平均值 centroid = "centre of gravity",它给出了更实际的区域间通勤距离。

regions <- st_read("~/Downloads/regions.shp")

ea <- st_read("~/Downloads/enumerator_areas.shp")

intersected <- st_intersection(regions, ea)

sub_region_centroids <- st_centroids(intersected)

我 运行 遇到困难的地方是如何找到平均质心。按地区分组无效。

mean_centroid <- sub_region_centroids %>%
                          group_by(region_name) %>%
                          summarise(mean_centroid = mean(geometry))

Warning messages:
1: In mean.default(geometry) :
  the argument is not numeric or logical: returning NA

我哪里错了?

我也不知道如何将平均质心添加回原始区域的对象。

希望有人能帮助我。

计算多个质心的总体加权平均值是一个有趣的问题。

您可以考虑这样的方法 - 我计算北卡罗来纳州三个城市的加权质心(利用 {sf} 附带的众所周知且备受喜爱的 nc.shp 文件) .

工作流使用 tidyr::uncount() 首先将每个人口的城市点相乘,然后将(许多)相乘的点合并为一个多点特征。并且多点特征定义了sf::st_centroid()操作(QED)。最后的sf::st_as_sf()只是润色

library(sf)
library(dplyr)
library(ggplot2)

# included with sf package
shape <- st_read(system.file("shape/nc.shp", package="sf")) 

# dramatis personae; population as per Wikipedia
cities <- data.frame(name = c("Raleigh", "Greensboro", "Wilmington"),
                  x = c(-78.633333, -79.819444, -77.912222),
                  y = c(35.766667, 36.08, 34.223333),
                  population = c(467665, 299035, 115451)) %>% 
  st_as_sf(coords = c("x", "y"), crs = 4326)

# a quick overview of facts on ground 
ggplot() +
   geom_sf(data = shape) + # polygon of North Carolina
   geom_sf(data = cities, color = "red") # 3 cities
   

# unweighted centroid / a baseline    
plain_center <- cities %>% 
  st_geometry() %>% # pull just geometry
  st_combine() %>%  # from many points to a single multipoint
  st_centroid() %>% # compute centroid of the multipoint
  st_as_sf() # make it a sf object again

# the fun is here!!
center_of_centers <- cities %>% 
  tidyr::uncount(population) %>% # multiply rows according to population
  st_geometry() %>% # pull just geometry
  st_combine() %>%  # from many points to a single multipoint
  st_centroid() %>% # compute centroid of the multipoint
  st_as_sf() # make it a sf object again

# finished result
ggplot() +
  geom_sf(data = shape, color = "gray75") + # polygon of North Carolina
  geom_sf(data = cities, color = "red") + # 3 cities
  geom_sf(data = plain_center, color = "green") + # unweighted center
  geom_sf(data = center_of_centers, color = "blue", pch = 4) # population weighted center

按照@Jindra Lacko 的很好的例子,这里是如何使用纬度和经度的加权平均值来完成的。

library(sf)
library(dplyr)
library(ggplot2)

# weighted mean of lat and long
center_weighted <- cities %>%
  mutate(lon = sf::st_coordinates(.)[,1],
         lat = sf::st_coordinates(.)[,2]) %>%
  st_drop_geometry() %>%
  summarize(across(c(lon, lat), weighted.mean, w = population)) %>%
  st_as_sf(coords = c("lon", "lat"), crs = 4326)


# plot it
ggplot() +
  geom_sf(data = shape, color = "gray75") + 
  geom_sf(data = cities, color = "red") + 
  geom_sf(data = center_weighted, color = "blue", pch = 4)


数据

# set up example data
shape <- st_read(system.file("shape/nc.shp", package="sf")) 
cities <- data.frame(name = c("Raleigh", "Greensboro", "Wilmington"),
                     x = c(-78.633333, -79.819444, -77.912222),
                     y = c(35.766667, 36.08, 34.223333),
                     population = c(467665, 299035, 115451)) %>% 
  st_as_sf(coords = c("x", "y"), crs = 4326)