R:sfnetworks:如何在同一数据集中查找多个 A 和 B 位置之间的路线

R: sfnetworks: How to find routes between multiple A and B locations in a same dataset

这是我的数据集

df<-tribble(
  ~"shop.x",~"shop.y", ~"cust.x", ~"cust.y",
  78.100378,    9.944226,   78.096318,  9.954789,
  78.101155,    9.932190,   78.089824,  9.929975,
  78.141887,    9.928319,   78.110863,  9.952235,
  78.100381,    9.944226,   78.104066,  9.97013,
  78.097206,    9.948872,   78.11631,   9.947862
)

df 数据集包含商店和顾客的位置。

我想在 R 中使用 OSM 地图为每一行(每个商店到客户位置)创建最短路径路线。是否可以使用 sfnetworks?

本地路网数据为here

首先,由于此数据框主要包含商店和客户的 X 和 Y 坐标,我将它们转换为 sf 对象。每组两个对象。

# Load packages
library(tidyverse)
library(sf)
library(sfnetworks)
library(tidygraph)

# Load the data
df <- tribble(
  ~"shop.x",~"shop.y", ~"cust.x", ~"cust.y",
  78.100378,    9.944226,   78.096318,  9.954789,
  78.101155,    9.932190,   78.089824,  9.929975,
  78.141887,    9.928319,   78.110863,  9.952235,
  78.100381,    9.944226,   78.104066,  9.97013,
  78.097206,    9.948872,   78.11631,   9.947862
)

# Convert into sf objects
shop = st_as_sf(df[,1:2], crs = 4326, coords = c("shop.x", "shop.y"))
cust = st_as_sf(df[,3:4], crs = 4326, coords = c("cust.x", "cust.y"))

道路是LINESTRINGS,可以转换成sfnetwork对象。网络需要清理。有关如何进行网络预处理的更多信息 here

## I downloaded the data attached and saved it locally 
roads_dir = "data/roads.shp"
roads = st_read(roads_dir, crs = 4326)
#> Reading layer `Roads' from data source 
#> Simple feature collection with 6915 features and 0 fields
#> Geometry type: LINESTRING
#> Dimension:     XY
#> Bounding box:  xmin: 78.0217 ymin: 9.832762 xmax: 78.22482 ymax: 10.04193
#> Geodetic CRS:  WGS 84

# Convert into an sfnetwork
roads_sfn = as_sfnetwork(roads, directed = FALSE)

# Do some network cleaning
roads_clean = roads_sfn %>% 
  convert(to_spatial_subdivision, .clean = TRUE) %>% 
  convert(to_spatial_smooth, .clean = TRUE) 

要计算路径,我们可以对 st_network_paths() 函数使用 mapply 函数,将 from 参数传递给商店的位置,将 to 参数传递给客户的位置。因此,路径是按顺序为每个组合计算的。

# Calculate the specified paths.
paths = mapply(
  st_network_paths,
  from = shop,
  to = cust,
  MoreArgs = list(x = roads_clean)
)["node_paths", ] %>%
  unlist(recursive = FALSE)
#> although coordinates are longitude/latitude, st_nearest_points assumes that they are planar
#> although coordinates are longitude/latitude, st_nearest_points assumes that they are planar
#> Warning: Although argument from has length > 1, only the first element is used

输出是一个包含五个元素的列表,其中包含每条路线的节点索引,对应于原始网络中的节点。

paths[[1]]
#>  [1]  1842  1843 12191 12190   232  7977  7843 12174  8244  8205  7914  8139
#> [13]  8209  7958  7957  8229  8230  8328

如果我们想得到路径作为网络本身,我们可以将原始网络切片为:

roads_clean %>%
  activate("nodes") %>%
  slice(paths[[1]])
#> # A sfnetwork with 18 nodes and 17 edges
#> #
#> # CRS:  EPSG:4326 
#> #
#> # An unrooted tree with spatially explicit edges
#> #
#> # Node Data:     18 x 1 (active)
#> # Geometry type: POINT
#> # Dimension:     XY
#> # Bounding box:  xmin: 78.09568 ymin: 9.943727 xmax: 78.10051 ymax: 9.955158
#>              geometry
#>           <POINT [°]>
#> 1 (78.10001 9.946228)
#> 2 (78.10051 9.943727)
#> 3 (78.10017 9.945039)
#> 4 (78.09918 9.951894)
#> 5 (78.09895 9.953372)
#> 6 (78.09647 9.955099)
#> # ... with 12 more rows
#> #
#> # Edge Data:     17 x 3
#> # Geometry type: LINESTRING
#> # Dimension:     XY
#> # Bounding box:  xmin: 78.09568 ymin: 9.943727 xmax: 78.10051 ymax: 9.955158
#>    from    to                                                  geometry
#>   <int> <int>                                          <LINESTRING [°]>
#> 1     2     3 (78.10051 9.943727, 78.10029 9.944423, 78.10017 9.945039)
#> 2     6     7                    (78.09647 9.955099, 78.09877 9.954435)
#> 3    12    13                    (78.09569 9.955158, 78.09568 9.954763)
#> # ... with 14 more rows