基于HYRIV_ID识别HydroSHEDS河网中目标点的上游河段
基于HydroSHEDS河网数据识别上游河段的实现与优化需求
我采用HydroSHEDS的全球河网数据,该数据集中每个河段拥有唯一的8位编码(HYRIV_ID),本次任务仅依赖NEXT_DOWN字段(存储下游河段的编码)。
为复现目标数据集,我编写了如下代码:
a <- c(41397427, 41397438, 41397439, 41397440, 41397466, 41397467, 41397494, 41397495, 41397512, 41397513, 41397514, 41397566, 41397584) b <- c(41397438, 41397494, 41397466, 41397439, 41397438, 41397440, 41397401, 41397440, 41397466, 41397439, 41397495, 41397495, 41397494) # 包含河段ID(HYRIV_ID)和下游河段(NEXT_DOWN)的数据框 df <- data.frame(HYRIV_ID = a, NEXT_DOWN = b) # 目标点A和B的HYRIV_ID id <- c(41397494, 41397495)

我需要利用向量id中的HYRIV_ID,识别点A和B的所有上游河段。由于实际数据包含更多目标点,我编写了循环遍历id中的所有编码,尝试代码如下:
# 注意:循环可运行,但i=1(点A)的输出不正确,仅识别了第一层上游河段 pt_up <- list() # 创建列表存储每个目标编码的上游HYRIV_ID for (i in 1:length(id)){ n <- id[[i]] # 创建存储目标HYRIV_ID及所有上游河段编码的向量 tmp_id <- df[df$NEXT_DOWN == id[[i]],]$HYRIV_ID # 识别以n为下游的河段 # 若目标河段为最上游,则无上游河段 if(length(tmp_id) == 0){ n <- n # 否则,需继续查找上游河段 }else{ # 若tmp_id长度大于1,需查找其中每个HYRIV_ID的上游河段 # 用第二层循环遍历tmp_id中的编码 for (j in 1:length(tmp_id)){ tmp_id2 <- df[df$NEXT_DOWN == tmp_id[[j]],]$HYRIV_ID if(length(tmp_id2) == 0){ n <- append(n, tmp_id[[j]]) # 若tmp_id2无上游河段,则将tmp_id中的编码加入n }else{ n <- append(n, tmp_id2) } } } pt_up[[i]] <- n # 将目标河段的上游HYRIV_ID加入列表 names(pt_up)[i] <- id[[i]] # 为列表元素命名以区分目标河段 }
该代码对B点(i=2)有效,其上游河段均为终点:
但对于存在多个分支的A点,需要重复第二层循环以遍历所有新找到的河段。我认为可将第二层循环放入repeat函数中,但不确定具体实现方式:
更新
我最终用repeat循环实现了需求,但确信存在更简洁的解决方案!
pt_up <- list() # 创建列表存储每个目标编码的上游HYRIV_ID for (i in 1:length(id)){ n <- id[[i]] # 创建存储目标HYRIV_ID及所有上游河段编码的向量 tmp_id <- df[df$NEXT_DOWN == id[[i]],]$HYRIV_ID # 识别以n为下游的河段 # 若目标河段为最上游,则无上游河段 if(length(tmp_id) == 0){ n <- n # 否则,需继续查找上游河段 }else{ # 若tmp_id长度大于1,需查找其中每个HYRIV_ID的上游河段 # 用第二层循环遍历tmp_id中的编码 n <- append(n, tmp_id) # 加入第一层上游河段的HYRIV_ID tmp_id2 <- tmp_id # 创建新向量用于循环内更新,避免覆盖原数据 ####### 新增代码段 ###### repeat{ # 此处添加repeat循环 for (j in 1:length(tmp_id2)){ # 遍历tmp_id2中的所有HYRIV_ID,更新后重复执行 if(length(df[df$NEXT_DOWN == tmp_id2[[j]],]$HYRIV_ID) == 0){ n <- n # 若tmp_id2无上游河段,保持n不变 }else{ id2 <- df[df$NEXT_DOWN == tmp_id2[[j]],]$HYRIV_ID # tmp_id2中编码对应的上游HYRIV_ID n <- append(n, id2) # 将编码加入n } } tmp_id2 <- id2 # 更新tmp_id2为新找到的编码,以便重复循环 if (length(df[df$NEXT_DOWN %in% tmp_id2,]$HYRIV_ID) == 0 & unique(tmp_id2 %in% n) == TRUE){ break } # 当无剩余上游河段时终止repeat循环 } ####### 新增代码段结束 ###### pt_up[[i]] <- n # 将目标河段的上游HYRIV_ID加入列表 names(pt_up)[i] <- id[[i]] # 为列表元素命名以区分目标河段 } }
内容的提问来源于stack exchange,提问作者FAmorim
相关产品推荐
相关产品推荐

