R语言中如何将sf network的有向网络转为无向网络?
问题:无向sf网络添加步行路段后变为有向网络的解决方法
我用道路数据构建sf network,计划添加从设施点到最近道路的步行路段(设施点到最近道路的直线)。按步骤操作后,最终得到的却是仅可单向遍历的有向网络。
初始数据与网络构建代码
# required packages library(sf) library(sfnetworks) library(tidygraph) library(tidyverse) # creating a hypotetical road p3 = st_point(c(2, 1)) p4 = st_point(c(3, 1)) p5 = st_point(c(4, 1)) p6 = st_point(c(3, 2)) p7 = st_point(c(3, 0)) p9 = st_point(c(4, 2)) p10 = st_point(c(4, 0)) p14 = st_point(c(5.8, 1)) p15 = st_point(c(6, 1.2)) p16 = st_point(c(6.2, 1)) p17 = st_point(c(6, 0.8)) p18 = st_point(c(6, 2)) p19 = st_point(c(6, -1)) p20 = st_point(c(7, 1)) l2 = st_sfc(st_linestring(c(p3, p4, p5))) l3 = st_sfc(st_linestring(c(p6, p4, p7))) l5 = st_sfc(st_linestring(c(p9, p5, p10))) l8 = st_sfc(st_linestring(c(p5, p14))) l9 = st_sfc(st_linestring(c(p15, p14))) l10 = st_sfc(st_linestring(c(p16, p15))) l11 = st_sfc(st_linestring(c(p14, p17))) l12 = st_sfc(st_linestring(c(p17, p16))) l13 = st_sfc(st_linestring(c(p15, p18))) l14 = st_sfc(st_linestring(c(p17, p19))) l15 = st_sfc(st_linestring(c(p16, p20))) road = c(l2, l3, l5, l8, l9, l10, l11, l12, l13, l14, l15) facility = st_sf(id = 1:2, st_sfc(st_point(c(4.5, 1.5)), st_point(c(2.5, 0.5))), crs = 20138) # visualizing location of facility and road plot(st_geometry(road), col = "gray", lwd = 4) plot(st_geometry(facility), col = "red", add = TRUE)
步行路段添加与网络合并代码
# building a network net = as_sfnetwork(road, directed = FALSE) st_crs(net) = 20138 net = net %>% convert(to_spatial_subdivision) net # creating a walking lines new_network = st_network_blend(net, facility) node_coords = new_network %>% activate("nodes") %>% st_coordinates() node_coords = st_as_sf(as.data.frame(node_coords), coords = c("X","Y"), remove = FALSE) library(nngeo) walking_lines = st_as_sf(st_connect(facility, node_coords)) st_geometry(walking_lines) <- "geometry" # visualizing walking lines plot(st_geometry(new_network, "edges"), col = "gray", lwd = 4) plot(st_geometry(new_network, "nodes"), pch = 20, cex = 2, add = TRUE) plot(st_geometry(net2, "edges"), col = "red", lwd = 4, add = TRUE)
最终网络合并代码
net2 = as_sfnetwork(walking_lines, directed = FALSE) joined = st_network_join(net2, new_network) joined
经with_graph(joined, graph_component_count())验证,网络是连通的,但属于有向网络,需要转为无向网络或提供替代实现方法。
解决方案
方法一:直接将合并后的有向网络转为无向网络
使用convert(to_undirected)函数为每条有向边添加反向边,确保网络支持双向遍历:
# 将合并后的有向网络转为无向 undirected_joined = joined %>% convert(to_undirected) # 验证网络属性 undirected_joined
方法二:简化步行路段添加流程(从根源避免有向问题)
不需要单独创建步行路段网络再合并,直接生成步行边并绑定到原无向网络中,步骤如下:
# 获取设施点到网络的最近节点 nearest_nodes_idx = st_nearest_feature(facility, net %>% activate("nodes")) nearest_nodes_geom = net %>% activate("nodes") %>% slice(nearest_nodes_idx) %>% st_geometry() # 生成设施点到最近节点的步行边 walking_edges = st_connect(facility, nearest_nodes_geom) %>% st_as_sf() # 将步行边直接添加到原无向网络 final_undirected_net = net %>% activate("edges") %>% bind_rows(walking_edges) %>% convert(to_spatial_subdivision) # 确保节点连接逻辑正确 # 验证网络为无向属性 final_undirected_net
关键说明
st_network_join在合并网络时,可能因节点匹配的方向逻辑导致网络转为有向,直接转换为无向是最快速的修复方式- 简化流程中,直接绑定步行边到原无向网络,能全程保持网络的无向属性,同时避免额外的网络合并操作
内容的提问来源于stack exchange,提问作者Sisay
相关产品推荐
相关产品推荐

