如何在R中使用 “tbl_graphs”?

huangapple go评论145阅读模式
英文:

How to Use "tbl_graphs" in R?

问题

我正在使用R编程语言工作。

基于一个shapefile,我试图可视化/找出两个坐标之间的驾驶距离(例如,CN塔和多伦多皮尔逊机场)。

首先我加载了shapefile:

  1. library(sf)
  2. library(rgdal)
  3. library(sfnetworks)
  4. library(igraph)
  5. library(dplyr)
  6. library(tidygraph)
  7. # 设置shapefile的URL
  8. url <- "https://www12.statcan.gc.ca/census-recensement/2011/geo/RNF-FRR/files-fichiers/lrnf000r22a_e.zip"
  9. # 创建一个临时文件夹来下载和解压缩shapefile
  10. temp_dir <- tempdir()
  11. temp_file <- file.path(temp_dir, "lrnf000r22a_e.zip")
  12. # 下载shapefile到临时文件夹
  13. download.file(url, temp_file)
  14. # 从下载的zip文件中解压shapefile
  15. unzip(temp_file, exdir = temp_dir)
  16. # 使用rgdal包读取shapefile
  17. # 来源:https://gis.stackexchange.com/questions/456748/strategies-for-working-with-large-shapefiles/456798#456798
  18. a = st_read(file.path(temp_dir, "lrnf000r22a_e.shp"), query="select * from lrnf000r22a_e where PRUID_R ='35'")

shapefile看起来像这样:

  1. 包含570,706个要素和21个字段的简单要素集
  2. 几何类型:LINESTRING
  3. 维度:XY
  4. 边界框:xmin5963148 ymin665490.8 xmax7581671 ymax2212179
  5. 投影的CRSNAD83 / 加拿大统计局兰伯特
  6. 10个要素:
  7. OBJECTID NGD_UID NAME TYPE DIR AFL_VAL ATL_VAL AFR_VAL ATR_VAL CSDUID_L CSDNAME_L CSDTYPE_L CSDUID_R CSDNAME_R CSDTYPE_R PRUID_L PRNAME_L PRUID_R PRNAME_R RANK
  8. 1 4 3434819 <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> 3526003 Fort Erie T 3526003 Fort Erie T 35 Ontario 35 Ontario 5
  9. 2 5 1358252 South LINE <NA> <NA> <NA> <NA> <NA> 3551027 Gordon/Barrie Island MU 3551027 Gordon/Barrie Island MU 35 Ontario 35 Ontario 5
  10. 3 8 1778927 <NA> <NA> <NA> <NA> <NA> <NA> <NA> 3512054 Wollaston TP 3512054 Wollaston TP 35 Ontario 35 Ontario 5
  11. 4 11 731932 Albion RD <NA> <NA> <NA> 2010 2010 3520005 Toronto C 3520005 Toronto C 35 Ontario 35 Ontario 3
  12. 5 18 3123617 County 41 RD <NA> 640 708 635 709 3511015 Greater Napanee T 3511015 Greater Napanee T 35 Ontario 35 Ontario 3
  13. 6 20 4814160 <NA> <NA> <NA> <NA> <NA> <NA> <NA> 3553005 Greater Sudbury / Grand Sudbury CV 3553005 Greater Sudbury / Grand Sudbury CV 35 Ontario 35 Ontario 5
  14. 7 21 1817031 <NA> <NA> <NA> <NA> <NA> <NA> <NA> 3537028 Amherstburg T 3537028 Amherstburg T 35 Ontario 35 Ontario 5
  15. 8 24 4825761 <NA> <NA> <NA> <NA> <NA> <NA> <NA> 3554094 Timiskaming, Unorganized, West Part NO 3554094 Timiskaming, Unorganized, West Part NO 35 Ontario 35 Ontario 5
  16. 9 25 544891 Dunelm DR <NA> 1 9 2 10 3526053 St. Catharines CY 3526053 St. Catharines CY 35 Ontario 35 Ontario 5
  17. 10 28 1835384 Seven Oaks DR <NA> 730 974 731 975 3515005 Otonabee-South Monaghan TP 3515005 Otonabee-South Monaghan TP 35 Ontario 35 Ontario 5
  18. CLASS _ogr_geometry_
  19. 1 23 LINESTRING (7269806 859183,...
  20. 2 23 LINESTRING (6921247 1133452...
  21. 3 23 LINESTRING (7320857 1089403..

然后我尝试通过将道路网络视为图来计算距离:

  1. # 将shapefile转换为sfnetwork对象
  2. net <- as_sfnetwork(a)
  3. # 在WGS84(EPSG:4326)中定义两个兴趣点
  4. pt1 <- st_point(c(-79.61203, 43.68312))
  5. pt2 <- st_point(c(-79.61203, 43.64256))
  6. # 将点的CRS设置为WGS84(EPSG:4326)
  7. pt1 <- st_sfc(pt1, crs = 4326)
  8. pt2 <- st_sfc(pt2, crs = 4326)
  9. # 将点转换为网络的CRS
  10. pt1_transformed <- st_transform(pt1, st_crs(net))
  11. pt2_transformed <- st_transform(pt2, st_crs(net))
  12. # 找到变换后的兴趣点在网络上的最近点
  13. n1 <- st_nearest_feature(pt1_transformed, net)
  14. n2 <- st_nearest_feature(pt2_transformed, net)

从这里,我创建了一个“tbl_graph”:

  1. path <- net %>%
  2. activate(edges) %>%
  3. mutate(weight = edge_length()) %>%
  4. as_tbl_graph()
  5. > path
  6. <details>
  7. <summary>英文:</summary>
  8. I am working with the R programming language.
  9. **Based on a shapefile, I am trying to visualize/find out the driving distance between two coordinates (e.g. CN Tower and Toronto Pearson Airport).**
  10. First I loaded the shapefile:
  11. library(sf)
  12. library(rgdal)
  13. library(sfnetworks)
  14. library(igraph)
  15. library(dplyr)
  16. library(tidygraph)
  17. # Set the URL for the shapefile
  18. url &lt;- &quot;https://www12.statcan.gc.ca/census-recensement/2011/geo/RNF-FRR/files-fichiers/lrnf000r22a_e.zip&quot;
  19. # Create a temporary folder to download and extract the shapefile
  20. temp_dir &lt;- tempdir()
  21. temp_file &lt;- file.path(temp_dir, &quot;lrnf000r22a_e.zip&quot;)
  22. # Download the shapefile to the temporary folder
  23. download.file(url, temp_file)
  24. # Extract the shapefile from the downloaded zip file
  25. unzip(temp_file, exdir = temp_dir)
  26. # Read the shapefile using the rgdal package
  27. # source: https://gis.stackexchange.com/questions/456748/strategies-for-working-with-large-shapefiles/456798#456798
  28. a = st_read(file.path(temp_dir, &quot;lrnf000r22a_e.shp&quot;), query=&quot;select * from lrnf000r22a_e where PRUID_R =&#39;35&#39;&quot;)
  29. The shapefile looks something like this:
  30. Simple feature collection with 570706 features and 21 fields
  31. Geometry type: LINESTRING
  32. Dimension: XY
  33. Bounding box: xmin: 5963148 ymin: 665490.8 xmax: 7581671 ymax: 2212179
  34. Projected CRS: NAD83 / Statistics Canada Lambert
  35. First 10 features:
  36. OBJECTID NGD_UID NAME TYPE DIR AFL_VAL ATL_VAL AFR_VAL ATR_VAL CSDUID_L CSDNAME_L CSDTYPE_L CSDUID_R CSDNAME_R CSDTYPE_R PRUID_L PRNAME_L PRUID_R PRNAME_R RANK
  37. 1 4 3434819 &lt;NA&gt; &lt;NA&gt; &lt;NA&gt; &lt;NA&gt; &lt;NA&gt; &lt;NA&gt; &lt;NA&gt; 3526003 Fort Erie T 3526003 Fort Erie T 35 Ontario 35 Ontario 5
  38. 2 5 1358252 South LINE &lt;NA&gt; &lt;NA&gt; &lt;NA&gt; &lt;NA&gt; &lt;NA&gt; 3551027 Gordon/Barrie Island MU 3551027 Gordon/Barrie Island MU 35 Ontario 35 Ontario 5
  39. 3 8 1778927 &lt;NA&gt; &lt;NA&gt; &lt;NA&gt; &lt;NA&gt; &lt;NA&gt; &lt;NA&gt; &lt;NA&gt; 3512054 Wollaston TP 3512054 Wollaston TP 35 Ontario 35 Ontario 5
  40. 4 11 731932 Albion RD &lt;NA&gt; &lt;NA&gt; &lt;NA&gt; 2010 2010 3520005 Toronto C 3520005 Toronto C 35 Ontario 35 Ontario 3
  41. 5 18 3123617 County 41 RD &lt;NA&gt; 640 708 635 709 3511015 Greater Napanee T 3511015 Greater Napanee T 35 Ontario 35 Ontario 3
  42. 6 20 4814160 &lt;NA&gt; &lt;NA&gt; &lt;NA&gt; &lt;NA&gt; &lt;NA&gt; &lt;NA&gt; &lt;NA&gt; 3553005 Greater Sudbury / Grand Sudbury CV 3553005 Greater Sudbury / Grand Sudbury CV 35 Ontario 35 Ontario 5
  43. 7 21 1817031 &lt;NA&gt; &lt;NA&gt; &lt;NA&gt; &lt;NA&gt; &lt;NA&gt; &lt;NA&gt; &lt;NA&gt; 3537028 Amherstburg T 3537028 Amherstburg T 35 Ontario 35 Ontario 5
  44. 8 24 4825761 &lt;NA&gt; &lt;NA&gt; &lt;NA&gt; &lt;NA&gt; &lt;NA&gt; &lt;NA&gt; &lt;NA&gt; 3554094 Timiskaming, Unorganized, West Part NO 3554094 Timiskaming, Unorganized, West Part NO 35 Ontario 35 Ontario 5
  45. 9 25 544891 Dunelm DR &lt;NA&gt; 1 9 2 10 3526053 St. Catharines CY 3526053 St. Catharines CY 35 Ontario 35 Ontario 5
  46. 10 28 1835384 Seven Oaks DR &lt;NA&gt; 730 974 731 975 3515005 Otonabee-South Monaghan TP 3515005 Otonabee-South Monaghan TP 35 Ontario 35 Ontario 5
  47. CLASS _ogr_geometry_
  48. 1 23 LINESTRING (7269806 859183,...
  49. 2 23 LINESTRING (6921247 1133452...
  50. 3 23 LINESTRING (7320857 1089403..
  51. Then I tried to calculate the distance by treating the road network as a graph:
  52. # Convert the shapefile to an sfnetwork object
  53. net &lt;- as_sfnetwork(a)
  54. # Define the two points of interest in WGS84 (EPSG:4326)
  55. pt1 &lt;- st_point(c(-79.61203, 43.68312))
  56. pt2 &lt;- st_point(c(-79.61203, 43.64256))
  57. # Set the CRS of the points to WGS84 (EPSG:4326)
  58. pt1 &lt;- st_sfc(pt1, crs = 4326)
  59. pt2 &lt;- st_sfc(pt2, crs = 4326)
  60. # Transform the points to the CRS of the network
  61. pt1_transformed &lt;- st_transform(pt1, st_crs(net))
  62. pt2_transformed &lt;- st_transform(pt2, st_crs(net))
  63. # Find the nearest points on the network to the transformed points of interest
  64. n1 &lt;- st_nearest_feature(pt1_transformed, net)
  65. n2 &lt;- st_nearest_feature(pt2_transformed, net)
  66. From here, I create a &quot;tbl_graph&quot;:
  67. path &lt;- net %&gt;%
  68. activate(edges) %&gt;%
  69. mutate(weight = edge_length()) %&gt;%
  70. as_tbl_graph()
  71. &gt; path
  72. # A tbl_graph: 430824 nodes and 570706 edges
  73. #
  74. # A directed multigraph with 442 components
  75. #
  76. # Edge Data: 570,706 x 25 (active)
  77. from to OBJECTID NGD_UID NAME TYPE DIR AFL_VAL ATL_VAL AFR_VAL ATR_VAL CSDUID_L CSDNAME_L CSDTYPE~ CSDUID~ CSDNAME_R CSDTYP~ PRUID_L PRNAME~ PRUID_R PRNAME~ RANK CLASS `_ogr_geometry_` weight
  78. &lt;int&gt; &lt;int&gt; &lt;dbl&gt; &lt;chr&gt; &lt;chr&gt; &lt;chr&gt; &lt;chr&gt; &lt;chr&gt; &lt;chr&gt; &lt;chr&gt; &lt;chr&gt; &lt;chr&gt; &lt;chr&gt; &lt;chr&gt; &lt;chr&gt; &lt;chr&gt; &lt;chr&gt; &lt;chr&gt; &lt;chr&gt; &lt;chr&gt; &lt;chr&gt; &lt;chr&gt; &lt;chr&gt; &lt;LINESTRING [m]&gt; [m]
  79. 1 1 2 4 3434819 NA NA NA NA NA NA NA 3526003 Fort Erie T 3526003 Fort Erie T 35 Ontario 35 Ontario 5 23 (7269806 859183, 7269795 859166.~ 25.9
  80. 2 3 4 5 1358252 South LINE NA NA NA NA NA 3551027 Gordon/Bar~ MU 3551027 Gordon/Ba~ MU 35 Ontario 35 Ontario 5 23 (6921247 1133452, 6921258 113345~ 1245.
  81. 3 5 6 8 1778927 NA NA NA NA NA NA NA 3512054 Wollaston TP 3512054 Wollaston TP 35 Ontario 35 Ontario 5 23 (7320857 1089403, 7320903 108942~ 254.
  82. 4 7 8 11 731932 Albion RD NA NA NA 2010 2010 3520005 Toronto C 3520005 Toronto C 35 Ontario 35 Ontario 3 21 (7202555 935281.3, 7202653 93533~ 111.
  83. 5 9 10 18 3123617 County 41 RD NA 640 708 635 709 3511015 Greater Na~ T 3511015 Greater N~ T 35 Ontario 35 Ontario 3 21 (7403627 1039328, 7403431 103963~ 367.
  84. 6 11 12 20 4814160 NA NA NA NA NA NA NA 3553005 Greater Su~ CV 3553005 Greater S~ CV 35 Ontario 35 Ontario 5 21 (7042806 1222708, 7042838 122273~ 191.
  85. # ... with 570,700 more rows
  86. #
  87. # Node Data: 430,824 x 1
  88. `_ogr_geometry_`
  89. &lt;POINT [m]&gt;
  90. 1 (7269806 859183)
  91. 2 (7269790 859162.7)
  92. 3 (6921247 1133452)
  93. # ... with 430,821 more rows
  94. **My Question:** From here, I am not sure how to use the tbl_graph to find the distance between the two points n1 and n2:
  95. &gt; n1
  96. [1] 110393
  97. &gt; n2
  98. [1] 319271
  99. I think n1 and n2 correspond to the &quot;to&quot; and &quot;from&quot; columns in the &quot;path&quot; tbl_graph - but I am not sure how to use the tbl_graph to find out the distance between n1 and n2.
  100. Can someone please show me how to do this?
  101. Thanks!
  102. </details>
  103. # 答案1
  104. **得分**: 4
  105. `n1` `n2` 是一个名为 `net` `tibble` 的行号索引。这些值可以用于子集化图列表,或者作为 `igraph::shortest_paths()` 函数的 `from` `to` 参数。在这种情况下,如果你使用 `n1` `n2` 来查找最短路径,你可能会看到一些相当奇怪的结果,或者可能只是一个空列表。
  106. 此外,`sfnetworks` 对象 `net` 继承自 `tbl_graph` `igraph`,因此 `tiynetworks` `igraph` 的方法应该在不需要转换的情况下正常工作。将 `net` 转换为 `path`,并添加权重,不会更接近所需的路径。它仍然是几乎与之前相同的 `tbl_graph`,只是没有了空间图层。`sfnetworks` 还实现了满足你的主要目标所需的所有内容:`st_network_paths()` 和/或 `to_spatial_shortest_paths()` 转换器。
  107. `sfnetwork` 也被配置为有向(这是默认设置),这很可能会破坏所有的路由尝试,至少在这种情况下。
  108. `st_network_paths()` 方法示例:
  109. ``` r
  110. library(sf)
  111. library(sfnetworks)
  112. library(mapview)
  113. library(dplyr)
  114. library(ggplot2)
  115. # ...(代码的其余部分,已经在上面提供了)

igraph 方法示例:

  1. library(igraph)
  2. # ...(代码的其余部分,已经在上面提供了)

tidygraphsfnetworks 的 morphers 示例:

  1. library(tidygraph)
  2. # ...(代码的其余部分,已经在上面提供了)

请注意,以上示例代码中包含了其他内容,只提供了与翻译请求相关的部分。

英文:

n1 & n2 are indeces, row numbers of one of the net tibbles. Those values can be used to subset graph lists or used as from and to parameters for igraph::shortest_paths(). In this case, n1 & n2 probably targeted edges tibble as nodes were not activated first. Means that if you used those n1 & n2 for finding shortest path, you probably witnessed some rather funky results. Or perhaps just an empty list.

Also, the sfnetworks object, net, inherits from tbl_graph and also igraph, so tiynetworks and igraph methods should work just fine on netwithout converting it first. net -> path conversion, while adding weights, leads no closer to desired route. It's still (almost) the same tbl_graph it was before, now without a spatial layer. sfnetworks also implements all what's needed for your main objective: st_network_paths() and/or to_spatial_shortest_paths() morpher.

sfnetwork was also configured to be directed (well, it's a default setting), this most likely will ruin all routing attempts, at least in this case.

sfnetworks::st_network_paths() approach

  1. library(sf)
  2. library(sfnetworks)
  3. library(mapview)
  4. library(dplyr)
  5. library(ggplot2)
  6. shp_url &lt;- &quot;https://www12.statcan.gc.ca/census-recensement/2011/geo/RNF-FRR/files-fichiers/lrnf000r22a_e.zip&quot;
  7. if (!file.exists(basename(shp_url))) curl::curl_download(shp_url, basename(shp_url), quiet = FALSE)
  8. # keep archive zipped;
  9. # predefined bbox, small patch in Toronto,
  10. # covers cover both points and leaves plenty of routing options
  11. a &lt;- read_sf(paste0(&quot;/vsizip/&quot;, basename(shp_url)),
  12. wkt_filter = &quot;POLYGON ((7200615 918857, 7211499 918857, 7211499 933387, 7200615 933387, 7200615 918857))&quot;)
  13. a
  14. #&gt; Simple feature collection with 7584 features and 21 fields
  15. #&gt; Geometry type: LINESTRING
  16. #&gt; Dimension: XY
  17. #&gt; Bounding box: xmin: 7199959 ymin: 918285.7 xmax: 7211930 ymax: 934030.6
  18. #&gt; Projected CRS: NAD83 / Statistics Canada Lambert
  19. #&gt; # A tibble: 7,584 &#215; 22
  20. #&gt; OBJECTID NGD_UID NAME TYPE DIR AFL_VAL ATL_VAL AFR_VAL ATR_VAL CSDUID_L
  21. #&gt; &lt;dbl&gt; &lt;chr&gt; &lt;chr&gt; &lt;chr&gt; &lt;chr&gt; &lt;chr&gt; &lt;chr&gt; &lt;chr&gt; &lt;chr&gt; &lt;chr&gt;
  22. #&gt; 1 668 4668376 Dixie RD &lt;NA&gt; 2520 2520 2531 2543 3521005
  23. #&gt; 2 874 4617171 401 HWY &lt;NA&gt; &lt;NA&gt; &lt;NA&gt; &lt;NA&gt; &lt;NA&gt; 3521005
  24. #&gt; 3 2252 4092570 Breton AVE &lt;NA&gt; 178 300 175 295 3521005
  25. #&gt; 4 3320 485941 Kipling AVE &lt;NA&gt; &lt;NA&gt; &lt;NA&gt; &lt;NA&gt; &lt;NA&gt; 3520005
  26. #&gt; 5 3698 4775771 Eringa… DR &lt;NA&gt; 99 105 108 120 3520005
  27. #&gt; 6 3700 507598 Bristol RD W &lt;NA&gt; &lt;NA&gt; &lt;NA&gt; &lt;NA&gt; 3521005
  28. #&gt; 7 4472 4683515 Airport RD &lt;NA&gt; &lt;NA&gt; &lt;NA&gt; &lt;NA&gt; &lt;NA&gt; 3521005
  29. #&gt; 8 4759 5779033 401 HWY &lt;NA&gt; &lt;NA&gt; &lt;NA&gt; &lt;NA&gt; &lt;NA&gt; 3520005
  30. #&gt; 9 5051 505570 Grand … RD &lt;NA&gt; 3496 3530 3511 3525 3521005
  31. #&gt; 10 5533 5876974 Yorkda… CRES &lt;NA&gt; 31 67 30 58 3520005
  32. #&gt; # ℹ 7,574 more rows
  33. #&gt; # ℹ 12 more variables: CSDNAME_L &lt;chr&gt;, CSDTYPE_L &lt;chr&gt;, CSDUID_R &lt;chr&gt;,
  34. #&gt; # CSDNAME_R &lt;chr&gt;, CSDTYPE_R &lt;chr&gt;, PRUID_L &lt;chr&gt;, PRNAME_L &lt;chr&gt;,
  35. #&gt; # PRUID_R &lt;chr&gt;, PRNAME_R &lt;chr&gt;, RANK &lt;chr&gt;, CLASS &lt;chr&gt;,
  36. #&gt; # geometry &lt;LINESTRING [m]&gt;
  37. # from / to points for routing:
  38. pts &lt;- tribble(~point, ~lon, ~lat,
  39. &quot;pt1&quot;, -79.61203, 43.68312,
  40. &quot;pt2&quot;, -79.61203, 43.64256) %&gt;%
  41. st_as_sf(coords =c(&quot;lon&quot;, &quot;lat&quot;), crs = st_crs(4326)) %&gt;%
  42. st_transform(st_crs(a))
  43. # create un-directed network (default is directed),
  44. # store edge lenghts as weights
  45. net &lt;- as_sfnetwork(a, directed = FALSE) %&gt;%
  46. activate(&quot;edges&quot;) %&gt;%
  47. mutate(weight = edge_length())
  48. # get paths between pt1 &amp; pt2 with sfnetwork
  49. paths_sfn &lt;- st_network_paths(net,
  50. from = pts[pts$point == &quot;pt1&quot;, ],
  51. to = pts[pts$point == &quot;pt2&quot;, ],
  52. weights = &quot;weight&quot;)
  53. paths_sfn
  54. #&gt; # A tibble: 1 &#215; 2
  55. #&gt; node_paths edge_paths
  56. #&gt; &lt;list&gt; &lt;list&gt;
  57. #&gt; 1 &lt;int [54]&gt; &lt;int [53]&gt;
  58. # includes list of edge indeces that form the path:
  59. paths_sfn$edge_paths[[1]]
  60. #&gt; [1] 1027 1032 1295 697 121 2704 2702 2778 1125 1280 4364 1360 235 1686 2048
  61. #&gt; [16] 6115 2266 865 2508 7511 7179 2956 1823 5139 1055 5929 3684 3417 5960 1196
  62. #&gt; [31] 3383 1603 1975 1159 6250 5814 58 1964 3593 4423 3477 4940 383 5784 2362
  63. #&gt; [46] 4120 7251 1970 4834 5155 624 1935 5134
  64. # get edges with matching indeces:
  65. route &lt;- net %&gt;%
  66. activate(&quot;edges&quot;) %&gt;%
  67. slice(paths_sfn$edge_paths[[1]]) %&gt;%
  68. st_as_sf()
  69. # distance:
  70. sum(route$weight)
  71. #&gt; 7505.43 [m]
  72. # visualize
  73. mapview(list(pts, route))

如何在R中使用 “tbl_graphs”?<!-- -->

Path-finding and distance with igraph, using the same net object

  1. library(igraph)
  2. # to find node indeces, keep net nodes activated
  3. net &lt;- net %&gt;% activate(&quot;nodes&quot;)
  4. n1 &lt;- st_nearest_feature(pts[1,], net)
  5. n2 &lt;- st_nearest_feature(pts[2,], net)
  6. node1; node2
  7. #&gt; [1] 1560
  8. #&gt; [1] 3938
  9. # locate those on a map:
  10. net %&gt;%
  11. st_as_sf() %&gt;%
  12. slice(c(n1, n2)) %&gt;%
  13. mapview(layer.name = &quot;net nodes&quot;) +
  14. mapview(pts)

如何在R中使用 “tbl_graphs”?<!-- -->

  1. # as sfnetwork inherits from tbl_graph and igraph:
  2. class(net)
  3. #&gt; [1] &quot;sfnetwork&quot; &quot;tbl_graph&quot; &quot;igraph&quot;
  4. # we can use igraph::shortest_paths() with our sfnetwork object:
  5. paths_ig &lt;- shortest_paths(net, n1, n2, output = &quot;epath&quot;)
  6. # paths_ig$epath is a list of edges:
  7. str(paths_ig)
  8. #&gt; List of 4
  9. #&gt; $ vpath : NULL
  10. #&gt; $ epath :List of 1
  11. #&gt; ..$ : &#39;igraph.es&#39; int [1:53] 1027 1032 1295 697 121 2704 2702 2778 1125 1280 ...
  12. #&gt; .. ..- attr(*, &quot;env&quot;)=&lt;weakref&gt;
  13. #&gt; .. ..- attr(*, &quot;graph&quot;)= chr &quot;aac7eae8-1b4f-11ee-a8b6-53eec7eb8cd4&quot;
  14. #&gt; $ predecessors : NULL
  15. #&gt; $ inbound_edges: NULL
  16. # when converted to integer, we&#39;ll have the same index list as
  17. # from sfnetwork::st_network_paths() :
  18. e &lt;- paths_ig$epath[[1]] %&gt;% as.integer()
  19. # check if those are indeed identical:
  20. identical(e, paths_sfn$edge_paths[[1]])
  21. #&gt; [1] TRUE
  22. # sum edge wights to get path distance:
  23. sum(E(net)[e]$weight)
  24. #&gt; 7505.43 [m]
  25. # we have not altered our original sf object (a) nor
  26. # sfnetwork object (net), so indeces should still match and we can use
  27. # e for subsetting: a[e,]
  28. ggplot() +
  29. geom_sf(data = a, color = &quot;grey80&quot;) +
  30. geom_sf(data = a[e,], linewidth = 1.5, alpha = .6) +
  31. geom_sf(data = pts, aes(color = point), size = 3) +
  32. coord_sf(datum = st_crs(a), ylim = c(922000, 930000)) +
  33. theme_light()

如何在R中使用 “tbl_graphs”?<!-- -->

Morphers by tidygraph and sfnetworks

There are also morphers, i.e. tidygraph::to_shortest_path (would work with previous n1 and n2 objects for from/ to) and sfnetworks::to_spatial_shortest_paths (takes sf points for from / to, just like st_network_paths()) , so there's no need to worry about picking relevant nodes / edges from the network, convert() output is already filtered:

  1. library(tidygraph)
  2. converted_net &lt;- net %&gt;% convert(to_spatial_shortest_paths, pts[1,], pts[2,])
  3. route_edges &lt;- st_as_sf(converted_net, &quot;edges&quot;)
  4. route_nodes &lt;- st_as_sf(converted_net, &quot;nodes&quot;)
  5. # route length:
  6. sum(route_edges$weight)
  7. #&gt; 7505.43 [m]
  8. ggplot() +
  9. geom_sf(data = a, color = &quot;grey80&quot;) +
  10. geom_sf(data = route_edges) +
  11. geom_sf(data = route_nodes, alpha = .2) +
  12. coord_sf(datum = st_crs(a), ylim = c(922000, 930000)) +
  13. theme_light()

如何在R中使用 “tbl_graphs”?<!-- -->

<sup>Created on 2023-07-05 with reprex v2.0.2</sup>

huangapple
  • 本文由 发表于 2023年6月19日 23:28:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/76508074.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定