st_network_blend()执行后如何保留原始sf点对象的属性列?
sfnetwork融合点后保留原始属性的解决方法
你不需要额外做关联,st_network_blend本身支持保留输入点的所有属性,你之前的错误是调用函数时仅传入了is_point单列,导致其他字段丢失。你后续尝试传入完整pts对象的操作是正确的,只是不知道怎么提取对应属性。
具体操作步骤
- 你给原始
pts用rowid_to_column生成唯一ID的操作完全正确,这个ID会在融合过程中保留 - 调用
st_network_blend时直接传入完整的pts对象,不要筛选列 - 融合后的网络节点中,成功吸附的点会完整保留你原始
pts的所有字段,原有网络节点的这些字段值为NA,直接过滤非空值就能得到对应融合点,所有原始属性都已存在,不需要额外做空间连接或者按行合并。
修正后可运行代码
library(sfnetworks) library(sf) library(dplyr) # 原有网络和点构造逻辑不变 n11 = st_point(c(0,0)) n12 = st_point(c(1,1)) e1 = st_sfc(st_linestring(c(n11, n12)), crs = 3857) n21 = n12 n22 = st_point(c(0,2)) e2 = st_sfc(st_linestring(c(n21, n22)), crs = 3857) n31 = n22 n32 = st_point(c(-1,1)) e3 = st_sfc(st_linestring(c(n31, n32)), crs = 3857) net = as_sfnetwork(c(e1,e2,e3)) pts = net %>% st_bbox() %>% st_as_sfc() %>% st_sample(10, type = "random") %>% st_set_crs(3857) %>% st_cast('POINT') %>% st_as_sf() %>% mutate(is_point = TRUE, dummy_var = paste0("A", seq_along(1:nrow(.)))) %>% tibble::rowid_to_column("origin_id") # 改个名字避免和后续网络节点ID混淆,逻辑更清晰 # 融合时直接传入完整pts对象,不要筛选列 tol = units::set_units(0.2, "m") net_blend = st_network_blend(net, pts, tolerance = tol) # 提取成功融合的点,原始属性已经全部保留在节点表中 out_pts <- st_as_sf(net_blend, "nodes") %>% filter(!is.na(origin_id)) # 过滤出原始点融合生成的节点 # 此时out_pts已经包含origin_id、is_point、dummy_var所有原始字段,可直接使用 # 如果需要关联原始pts后续计算得到的新属性,直接用origin_id关联即可 out_pts_join <- left_join(out_pts, st_drop_geometry(pts), by = "origin_id")
常见疑问说明
- 你之前给
out_pts新生成node_id再关联的方法完全不可行:新生成的ID是融合后整个网络的节点自增ID,和原始pts的ID没有任何对应关系,会出现匹配错位。 - 你查询到的
agr为NA是正常情况:这个是sf包的属性-几何关系标识,sfnetwork默认不会赋值,不影响属性值本身的存储和读取,直接查看st_as_sf(net_blend, "nodes")就能看到所有原始属性都正常存在。 - 如果存在多个原始点吸附到同一个网络位置融合为一个节点的情况,
st_network_blend默认会保留第一个匹配到的点的属性,你可以通过调整函数的merge_attributes参数自定义合并规则。
内容的提问来源于stack exchange,提问作者Josh J
相关产品推荐
相关产品推荐

