You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 15:45:05