如何用sf::st_distance()计算POINT轨迹要素的逐行欧氏距离?
使用sf::st_distance()计算轨迹相邻点的欧氏距离
当然可以用sf::st_distance()来实现这个需求,而且比手动用勾股定理更靠谱——尤其是当你的数据用的是经纬度坐标系时,它还能自动计算正确的球面距离,不会出现平面近似的误差。下面我一步步给你演示怎么操作:
第一步:准备示例数据
先把你没写完的示例代码补全,生成带分组的POINT类型sf对象:
library(sf) library(dplyr) set.seed(1) df <- data.frame( gr = c(rep("a",5), rep("b",5)), x = rnorm(10), y = rnorm(10) ) %>% st_as_sf(coords = c("x", "y"), crs = 4326) # 转换成sf对象,这里指定WGS84经纬度坐标系
第二步:计算相邻点距离
核心思路是给每个分组内的点配对它的下一个点,然后用st_distance()逐对计算距离。关键要用到lead()函数和st_distance()的by_element参数:
df_with_dist <- df %>% group_by(gr) %>% # 按轨迹分组,避免跨分组计算距离 arrange(gr) # 这里一定要确保点的顺序是轨迹的时间顺序!如果有时间列,改成arrange(gr, timestamp) mutate( next_geom = lead(geometry), # 获取同一分组的下一个位置的几何对象 # by_element=TRUE是核心:让函数计算对应位置的点对距离,而非全量距离矩阵 distance = st_distance(geometry, next_geom, by_element = TRUE) ) %>% ungroup() # 查看结果 print(df_with_dist)
关键参数说明
by_element = TRUE:如果不加这个参数,st_distance()会返回一个所有点之间的距离矩阵,而我们需要的是相邻行对应点的距离,这个参数就是用来指定逐元素配对计算的。group_by(gr):必须按轨迹分组,不然会把分组a的最后一个点和分组b的第一个点计算距离,这显然不符合轨迹的逻辑。- 排序:轨迹数据的顺序直接决定距离计算的正确性,如果你的数据有时间戳列,一定要用时间戳排序,比如
arrange(gr, timestamp),而不是仅仅按分组排序。
额外优势:适配不同坐标系
如果你的数据是经纬度(比如CRS=4326),手动用勾股定理计算的平面距离会有很大误差,而st_distance()会自动计算大圆距离(默认返回米为单位),结果更准确。如果需要转换单位,还可以用units包处理:
library(units) df_with_dist <- df_with_dist %>% mutate(distance_km = set_units(distance, km)) # 把距离转换成公里
这样就完美替代手动计算啦,代码更简洁,结果也更可靠~
内容的提问来源于stack exchange,提问作者Ratnanil
相关产品推荐
相关产品推荐

