R 如何将sf空间点列表转换为可路由图

R 如何将sf空间点列表转换为可路由图,r,graph,dodgr,R,Graph,Dodgr,我有一个sf dataframe对象,它有一系列表示公交线路形状的点。我想把这个对象变成一个可路由图,这样我就可以估计从c点到t点的遍历时间 以下是我使用dodgr的尝试,但我不确定我在这里做错了什么: library(dodgr) graph <- weight_streetnet(mydata, wt_profile = "motorcar", type_col="highway" , id_col = "id") 检查osmidx、wt配置文件时出错: 请指定用于加权街道网的类型

我有一个sf dataframe对象,它有一系列表示公交线路形状的点。我想把这个对象变成一个可路由图,这样我就可以估计从c点到t点的遍历时间

以下是我使用dodgr的尝试,但我不确定我在这里做错了什么:

library(dodgr)
graph <- weight_streetnet(mydata, wt_profile = "motorcar", type_col="highway" , id_col = "id")
检查osmidx、wt配置文件时出错: 请指定用于加权街道网的类型

可再现数据 数据如下图所示

mydata <- structure(list(shape_id = c(52421L, 52421L, 52421L, 52421L, 52421L, 
                              52421L, 52421L, 52421L, 52421L, 52421L, 52421L, 52421L, 52421L, 
                              52421L, 52421L, 52421L, 52421L, 52421L, 52421L, 52421L), length = structure(c(0.191422504106197, 
                              0.191422504106197, 0.191422504106197, 0.191422504106197, 0.191422504106197, 
                              0.191422504106197, 0.191422504106197, 0.191422504106197, 0.191422504106197, 
                              0.191422504106197, 0.191422504106197, 0.191422504106197, 0.191422504106197, 
                              0.191422504106197, 0.191422504106197, 0.191422504106197, 0.191422504106197, 
                              0.191422504106197, 0.191422504106197, 0.191422504106197), units = structure(list(
                              numerator = "km", denominator = character(0)), class = "symbolic_units"), class = "units"), 
                              geometry = structure(list(structure(c(-46.5623281998182, 
                              -23.5213458001468), class = c("XY", "POINT", "sfg")), structure(c(-46.562221, 
                              -23.52129), class = c("XY", "POINT", "sfg")), structure(c(-46.562121, 
                              -23.521235), class = c("XY", "POINT", "sfg")), structure(c(-46.5620233332577, 
                              -23.5211840000609), class = c("XY", "POINT", "sfg")), structure(c(-46.561925666591, 
                              -23.5211330000609), class = c("XY", "POINT", "sfg")), structure(c(-46.561828, 
                              -23.521082), class = c("XY", "POINT", "sfg")), structure(c(-46.5618098335317, 
                              -23.5212126666783), class = c("XY", "POINT", "sfg")), structure(c(-46.5617916670273, 
                              -23.5213433333544), class = c("XY", "POINT", "sfg")), structure(c(-46.5617735004869, 
                              -23.5214740000284), class = c("XY", "POINT", "sfg")), structure(c(-46.5617553339104, 
                              -23.5216046667004), class = c("XY", "POINT", "sfg")), structure(c(-46.5617371672978, 
                              -23.5217353333702), class = c("XY", "POINT", "sfg")), structure(c(-46.5617190006492, 
                              -23.5218660000379), class = c("XY", "POINT", "sfg")), structure(c(-46.5617008339645, 
                              -23.5219966667036), class = c("XY", "POINT", "sfg")), structure(c(-46.5616826672438, 
                              -23.5221273333671), class = c("XY", "POINT", "sfg")), structure(c(-46.5616645004869, 
                              -23.5222580000284), class = c("XY", "POINT", "sfg")), structure(c(-46.5616463336941, 
                              -23.5223886666877), class = c("XY", "POINT", "sfg")), structure(c(-46.5616281668651, 
                              -23.5225193333449), class = c("XY", "POINT", "sfg")), structure(c(-46.56161, 
                              -23.52265), class = c("XY", "POINT", "sfg")), structure(c(-46.5617355000207, 
                              -23.5226427501509), class = c("XY", "POINT", "sfg")), structure(c(-46.5618610000276, 
                              -23.5226355002012), class = c("XY", "POINT", "sfg"))), class = c("sfc_POINT", 
                              "sfc"), precision = 0, bbox = structure(c(xmin = -46.5623281998182, 
                              ymin = -23.52265, xmax = -46.56161, ymax = -23.521082), class = "bbox"), crs = structure(list(
                              epsg = 4326L, proj4string = "+proj=longlat +datum=WGS84 +no_defs"), class = "crs"), n_empty = 0L), 
                              id = c("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", 
                              "k", "l", "m", "n", "o", "p", "q", "r", "s", "t"), speed_kmh = c(11, 
                              11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 
                              11, 11, 11, 11)), sf_column = "geometry", agr = structure(c(shape_id = NA_integer_, 
                              length = NA_integer_, id = NA_integer_, speed_kmh = NA_integer_
                              ), class = "factor", .Label = c("constant", "aggregate", "identity"
                              )), row.names = c("1.13", "1.14", "1.15", "1.16", "1.17", "1.18", 
                              "1.19", "1.20", "1.21", "1.22", "1.23", "1.24", "1.25", "1.26", 
                              "1.27", "1.28", "1.29", "1.30", "1.31", "1.32"), class = c("sf", 
                              "data.table", "data.frame"))

我认为您可以通过将数据转换为igraph对象并使用igraph库中的功能来解决此问题。 您需要建立边和顶点以及权重值。 在igraph中,边是表示源和目标两个节点之间连接的链接。在这种情况下,链接是街道,点是节点

library(igraph)
GraphResult <- data.frame(Source = c(NULL), 
                      Target = c(NULL), 
                      weight  = c(NULL))

for (i in 1:(dim(mydata)[1] - 1)) {

  TempGraphResult <- data.frame(Source = c(0), 
                                Target = c(0), 
                                weight  = c(0))

  TempGraphResult$Source[1] <- mydata$id[i]
  TempGraphResult$Target[1] <- mydata$id[i + 1]
  TempGraphResult$weight[1] <- mydata$length[i]

  GraphResult <- rbind(GraphResult, TempGraphResult) }

MyIgraph <- graph_from_data_frame(GraphResult) 

#In this case works perfectly. But if you have more weight variables and even
#additional variables for the nodes, igraph have functions for constructing the
#igraph object

distances(MyIgraph, "c", "t") #returns 3.254183. Seems correct (0.1914225*17)
SquareMatrix <- distances(MyIgraph)

#*distances() is a function from igraph that performs the routing calculations.
可以实现更复杂的网络和计算路由。例如,可以设置道路的方向

也许道奇可以解决这个问题,但我不确定

weight_streetnet函数实际上只设计用于处理实际的街道网络,通常由osmdata::osmdata_sf/sp/sc函数生成。不过,它可以调整以处理类似的情况。需要做的主要工作是将点转换为了解点之间边的信息,如sf::LINESTRING对象:

此时,dodgr将直接从地理坐标计算并插入距离。通过替换d_加权值,还可以插入距离并用于布线:


请注意,对于这样的简单问题,igraph通常会更快,因为它使用一组权重计算路线。DoDGR在这个上下文中唯一的真正优势是使用双权重——$DY加权和$D值的能力-这样的路由是根据D$加权计算的,最后的距离根据D.< /P> < P >。如果你想把它包含在一个整洁的工作流程中,你也可以考虑使用SF和TiyGrand之间的混合。后者以tbl_图形类的形式为网络/图形提供了一个整洁的框架,该类是IGRAPHE的子类,因此,您可以在所有IGRAPHE函数中使用tbl_图形对象作为IGRAPHE对象。但是,您可以将节点和边分析为不可分割的,并使用过滤、选择、变异等功能。当然,这些TIBLES还可以包含一个几何体列表列,我们从sf中了解到该列,将地理信息添加到节点和边

这种方法还远远不够完美,改进是非常受欢迎的,但它仍然显示了另一种处理问题的方法

加载库。 图书馆管理员 图书馆 图书馆潮汐记录仪 图书馆记录仪 图书馆单位 与其他答案一样,我们需要在节点之间创建边。现在,我假设这些点只是按字母顺序连接起来的。然而,对于tidygraph方法,我们似乎需要数字ID而不是字符

将数字ID列添加到节点。 节点% 重命名id_chr=id%>% rowid_到_columnid%>% 选择id,id\u chr,所有内容 定义每条边的源节点和每条边的目标节点。 源%slice-n 目标%slice-1 编写一个函数,在源点和目标点的数据帧之间创建线。 pt2l%pullid, 长度=源%>%pulllength, 速度=来源%>%pullspeed\u公里小时, 几何=map2st\U几何资源、st\U几何目标、pt2l %>%st\U as\U sf%>%st\U集合\U crsst\U crsst节点 将时间列添加到边。 边缘% 突变速度=设定单位速度,km/h%>% 突变时间=长度/速度 清理节点数据。 节点% 选择长度、速度和公里小时 使用节点和边创建tbl_图形对象。 不幸的是,将边提供为sf对象对于tidygraph来说是有问题的。 因此,我们必须将其作为一个TIBLE提供。 图表%unlist%>% as_tbl_图 但绘制它也很容易,只需将节点和边导出为sf对象即可保留地理信息

ggplot() +
  geom_sf(data = graph %>% activate(edges) %>% as_tibble() %>% st_as_sf(), col = 'darkgrey') +
  geom_sf(data = graph %>% activate(nodes) %>% as_tibble() %>% st_as_sf(), col = 'darkgrey', size = 0.5) +
  geom_sf(data = path_graph %>% activate(edges) %>% as_tibble() %>% st_as_sf(), lwd = 1, col = 'firebrick') +
  geom_sf(data = path_graph %>% activate(nodes) %>% filter(id %in% c(from_node, to_node)) %>% as_tibble() %>% st_as_sf(), size = 2)

一篇r-spatial博客文章可能会出现在这个tidygraph sf方法上

只需一句评论:最少的示例代码使开发人员的工作更轻松。尽管问题很有趣,但期待看到并思考解决方案!“这很有帮助,”奥兰多说。再次感谢!我对这个话题特别感兴趣。更准确地讲,如何使用R计算不同格式的旅行时间和路线。例如,使用与OSM无关的.shp格式的行进行计算会很有用。但这应该是一件容易做的事,而且要有很大的灵活性;许多运输问题和许多运输分析机构都需要这样做。我看到类似ARCGIS的网络分析员在不久的将来为R开发。也许道奇就在那条路上。当你到达一个更高的位置时,请告诉我 不要回答你的问题。
net <- weight_streetnet (x, type_col = "shape_id", id_col = "id", wt_profile = 1)
net$from_id <- mydata$id [as.integer (net$from_id)]
net$to_id <- mydata$id [as.integer (net$to_id)]
net$d_weighted <- as.numeric (mydata$length [1])
dodgr_dists (net, from = "c", to = "t") # 236.0481
net$d <- net$d_weighted
dodgr_dists (net, from = "c", to = "t") # 3.254183
# A tbl_graph: 20 nodes and 19 edges
#
# An undirected simple graph with 1 component
#
# Node Data: 20 x 4 (active)
     id id_chr shape_id              geometry
  <int> <chr>     <int>           <POINT [°]>
1     1 a         52421 (-46.56233 -23.52135)
2     2 b         52421 (-46.56222 -23.52129)
3     3 c         52421 (-46.56212 -23.52124)
4     4 d         52421 (-46.56202 -23.52118)
5     5 e         52421 (-46.56193 -23.52113)
6     6 f         52421 (-46.56183 -23.52108)
# … with 14 more rows
#
# Edge Data: 19 x 6
   from    to    length   speed                               geometry      time
  <int> <int>      [km]  [km/h]                       <LINESTRING [°]>       [h]
1     1     2 0.1914225      11 (-46.56233 -23.52135, -46.56222 -23.5… 0.017402…
2     2     3 0.1914225      11 (-46.56222 -23.52129, -46.56212 -23.5… 0.017402…
3     3     4 0.1914225      11 (-46.56212 -23.52124, -46.56202 -23.5… 0.017402…
# … with 16 more rows
$vpath
$vpath[[1]]
+ 18/20 vertices, from e43a089:
 [1]  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20


$epath
$epath[[1]]
+ 17/19 edges from e43a089:
 [1]  3-- 4  4-- 5  5-- 6  6-- 7  7-- 8  8-- 9  9--10 10--11 11--12 12--13
[11] 13--14 14--15 15--16 16--17 17--18 18--19 19--20
# A tbl_graph: 18 nodes and 17 edges
#
# An undirected simple graph with 1 component
#
# Node Data: 18 x 4 (active)
     id id_chr shape_id              geometry
  <int> <chr>     <int>           <POINT [°]>
1     3 c         52421 (-46.56212 -23.52124)
2     4 d         52421 (-46.56202 -23.52118)
3     5 e         52421 (-46.56193 -23.52113)
4     6 f         52421 (-46.56183 -23.52108)
5     7 g         52421 (-46.56181 -23.52121)
6     8 h         52421 (-46.56179 -23.52134)
# … with 12 more rows
#
# Edge Data: 17 x 6
   from    to    length   speed                               geometry      time
  <int> <int>      [km]  [km/h]                       <LINESTRING [°]>       [h]
1     1     2 0.1914225      11 (-46.56212 -23.52124, -46.56202 -23.5… 0.017402…
2     2     3 0.1914225      11 (-46.56202 -23.52118, -46.56193 -23.5… 0.017402…
3     3     4 0.1914225      11 (-46.56193 -23.52113, -46.56183 -23.5… 0.017402…
# … with 14 more rows
path_graph %>%
    activate(edges) %>%
    as_tibble() %>%
    summarise(total_time = sum(time))
# A tibble: 1 x 1
  total_time
         [h]
1  0.2958348
ggplot() +
  geom_sf(data = graph %>% activate(edges) %>% as_tibble() %>% st_as_sf(), col = 'darkgrey') +
  geom_sf(data = graph %>% activate(nodes) %>% as_tibble() %>% st_as_sf(), col = 'darkgrey', size = 0.5) +
  geom_sf(data = path_graph %>% activate(edges) %>% as_tibble() %>% st_as_sf(), lwd = 1, col = 'firebrick') +
  geom_sf(data = path_graph %>% activate(nodes) %>% filter(id %in% c(from_node, to_node)) %>% as_tibble() %>% st_as_sf(), size = 2)