如何计算同一FieldID下所有点组合的距离(含对角线)
问题分析
你的代码之所以无法得到6个目标结果,是因为当前逻辑存在两个核心问题:
- 逐个遍历每个点,计算该点与同
FieldID下所有4个点的距离,导致重复计算点对(比如点A→点B和点B→点A会被算两次),还包含了点到自身的无效距离(值为0) - 最终每个
FieldID会生成16条记录(4×4),但你需要的是不重复的两两不同点对,也就是组合数C(4,2)=6个结果
解决方案
我们可以通过按FieldID分组,生成每组内所有唯一的点对组合,再针对性计算距离,避免无效计算。以下是两种高效的实现方式:
方法1:分组+组合函数处理
library(sf) library(dplyr) # 按FieldID分组,生成每组内唯一点对并计算距离 distance_df <- raps_filtered_sf %>% group_by(FieldID) %>% group_modify(function(group_data, group_key) { # 生成当前组内所有点的索引组合(不重复、不含自身) point_pairs <- combn(nrow(group_data), 2) # 遍历组合计算距离并整理结果 dist_results <- lapply(seq(ncol(point_pairs)), function(i) { idx1 <- point_pairs[1, i] idx2 <- point_pairs[2, i] tibble( SchlagID_1 = group_data$SchlagID[idx1], SchlagID_2 = group_data$SchlagID[idx2], distance = as.numeric(st_distance(group_data[idx1, ], group_data[idx2, ])) ) }) %>% bind_rows() return(dist_results) }) %>% ungroup()
方法2:向量化简洁处理
library(sf) library(dplyr) library(tidyr) distance_df <- raps_filtered_sf %>% # 为每个FieldID生成所有SchlagID的两两组合 group_by(FieldID) %>% mutate(pairs = list(combn(SchlagID, 2, simplify = FALSE))) %>% unnest(pairs) %>% # 拆分组合为两个独立的SchlagID列 mutate( s1 = map_chr(pairs, ~ .x[1]), s2 = map_chr(pairs, ~ .x[2]) ) %>% # 匹配对应点的几何信息 left_join(raps_filtered_sf, by = c("FieldID", "s1" = "SchlagID"), suffix = c("", "_1")) %>% left_join(raps_filtered_sf, by = c("FieldID", "s2" = "SchlagID"), suffix = c("", "_2")) %>% # 计算点对距离 mutate(distance = as.numeric(st_distance(geometry, geometry_2, by_element = TRUE))) %>% # 保留所需列并去重 select(FieldID, s1, s2, distance) %>% distinct() %>% ungroup()
结果说明
运行上述任意代码后,每个FieldID下会得到6条记录,对应4个点之间所有不重复的两两距离,其中自然包含你所说的正方形对角线距离(只要四个点的位置符合正方形顶点)。
内容的提问来源于stack exchange,提问作者KimChiya
相关产品推荐
相关产品推荐

