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

R语言按HEX_Tag_ID分组匹配坐标自动计算移动距离方法

问题描述

我借助points_in_circle函数按日期计算不同HEX_Tag_ID对应的移动距离,结果存为distance_m字段。现有代码的中心点坐标硬编码为ID是3D6.15341BBB4F在Datum为"2022-04-21"的经纬度,其他ID(比如3D6.15341BC60F)在2022-04-21的坐标和这个值不一致,导致这类ID的距离计算出错。
需要实现自动化计算逻辑:以每个唯一HEX_Tag_ID在Datum="2022-04-21"对应的经纬度作为自身的中心点,计算各ID的移动距离,后续新增ID时自动适配,不需要手动修改坐标参数。核心规则:中心点坐标必须取每个HEX_Tag_ID在Datum为"2022-04-21"的对应记录值。

现有错误代码:

library(spatialrisk)
Distance_ind <- points_in_circle(Distance_ind, lat_center = 51.93349, lon_center = 4.70912, lon = Longitude, lat = Latitude, radius = 1e6)

示例数据框Distance_ind结构如下:

structure(list(Datum_Tijd = structure(c(1650535073, 1653637570, 
1653285342, 1654242563, 1654578739, 1654837567, 1653899310, 1655108033, 
1653900853, 1653286920, 1653639081, 1654838913, 1653032146, 1655110494, 
1654580434, 1654244601, 1650533634), tzone = "", class = c("POSIXct", 
"POSIXt")), Datum = structure(c(19103, 19139, 19135, 19146, 19150, 
19153, 19142, 19156, 19142, 19135, 19139, 19153, 19132, 19156, 
19150, 19146, 19103), class = "Date"), Tijd = c("11:57:53", "09:46:10", 
"07:55:42", "09:49:23", "07:12:19", "07:06:07", "10:28:30", "10:13:53", 
"10:54:13", "08:22:00", "10:11:21", "07:28:33", "09:35:46", "10:54:54", 
"07:40:34", "10:23:21", "11:33:54"), Reader_ID = c("A0", "A0", 
"A0", "A0", "A0", "A0", "A0", "A0", "A0", "A0", "A0", "A0", "A0", 
"A0", "A0", "A0", "A0"), HEX_Tag_ID = c("3D6.15341BBB4F", "3D6.15341BBB4F", 
"3D6.15341BBB4F", "3D6.15341BBB4F", "3D6.15341BBB4F", "3D6.15341BBB4F", 
"3D6.15341BBB4F", "3D6.15341BBB4F", "3D6.15341BC60F", "3D6.15341BC60F", 
"3D6.15341BC60F", "3D6.15341BC60F", "3D6.15341BC60F", "3D6.15341BC60F", 
"3D6.15341BC60F", "3D6.15341BC60F", "3D6.15341BC60F"), Longitude = c(4.70912, 
4.70917, 4.70918, 4.70918, 4.70914, 4.70914, 4.70927, 4.70921, 
4.70904, 4.70903, 4.70906, 4.709, 4.70901, 4.70903, 4.70902, 
4.70902, 4.70925), Latitude = c(51.933491, 51.934189, 51.9342, 
51.934269, 51.93428, 51.934292, 51.934341, 51.934441, 51.932499, 
51.932491, 51.932468, 51.932369, 51.93235, 51.932339, 51.932331, 
51.932308, 51.934891), x = c(108366.11, 108370.273, 108370.972, 
108371.043, 108368.304, 108368.317, 108377.308, 108373.285, 108359.578, 
108358.882, 108360.921, 108356.692, 108357.36, 108358.724, 108358.028, 
108358.004, 108376.503), y = c(438553.585, 438631.208, 438632.425, 
438640.102, 438641.351, 438642.686, 438648.054, 438659.218, 438443.273, 
438442.39, 438439.812, 438428.836, 438426.716, 438425.479, 438424.595, 
438422.037, 438709.256), `Lengte_(cm)` = c(9.7, 9.7, 9.7, 9.7, 
9.7, 9.7, 9.7, 9.7, 11.2, 11.2, 11.2, 11.2, 11.2, 11.2, 11.2, 
11.2, 11.2), Geslacht = c("vrouw", "vrouw", "vrouw", "vrouw", 
"vrouw", "vrouw", "vrouw", "vrouw", "vrouw", "vrouw", "vrouw", 
"vrouw", "vrouw", "vrouw", "vrouw", "vrouw", "vrouw"), Sloot = c("22", 
"22", "22", "22", "22", "22", "22", "22", "22", "22", "22", "22", 
"22", "22", "22", "22", "22"), Lengte_8e_lichting = c(NA, NA, 
NA, NA, NA, NA, NA, 10.3, NA, NA, NA, NA, NA, 12.5, NA, NA, NA
), Lengteklasse = structure(c(4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 
6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L), .Label = c("6", "7", "8", 
"9", "10", "11", "12", "13"), class = "factor"), distance_m = c(0.111319490512219, 
77.8879654012696, 79.1440538153195, 86.8156131287763, 87.953110772786, 
89.2887843834125, 95.2906913528804, 106.044905287657, 110.454187269549, 
111.379609951795, 113.843032832766, 125.060674080157, 127.12861901825, 
128.277561285803, 129.201736097579, 131.75853920649, 156.213638336975
)), row.names = c(NA, -17L), class = c("tbl_df", "tbl", "data.frame"
))
解决方案

points_in_circle本身针对全局固定中心点设计,要实现按ID匹配对应中心点,两种方案都支持新增ID自动适配,无需手动修改参数:

方法1:分组计算(代码最简洁)

按HEX_Tag_ID分组,每组内先提取该ID在2022-04-21的经纬度作为中心点,再调用points_in_circle计算组内所有记录到中心点的距离,最后合并结果。

library(spatialrisk)
library(dplyr)

Distance_ind <- Distance_ind %>%
  group_by(HEX_Tag_ID) %>%
  group_modify(~{
    # 提取当前ID在2022-04-21的中心点坐标
    center_coords <- .x %>% filter(Datum == as.Date("2022-04-21")) %>% slice(1)
    # 组内计算距离
    points_in_circle(
      .x,
      lat_center = center_coords$Latitude,
      lon_center = center_coords$Longitude,
      lon = Longitude,
      lat = Latitude,
      radius = 1e6
    )
  }) %>%
  ungroup()

如果某个ID在2022-04-21有多条记录,上述代码默认取第一条作为中心点,需要取均值/其他聚合规则的话,修改center_coords的提取逻辑即可。

方法2:关联中心点逐行计算(大数据量下效率更高)

如果数据量较大,分组操作效率低,可以先提取所有ID的中心点做成查找表,关联回原表后直接用球面距离公式逐行计算,不需要循环调用points_in_circle。spatialrisk内置的haversine函数计算逻辑和points_in_circle完全一致,输出距离单位为米。

library(spatialrisk)
library(dplyr)

# 生成所有ID的中心点查找表
id_center <- Distance_ind %>%
  filter(Datum == as.Date("2022-04-21")) %>%
  select(HEX_Tag_ID, center_lon = Longitude, center_lat = Latitude) %>%
  distinct(HEX_Tag_ID, .keep_all = T)

# 关联中心点后逐行计算距离
Distance_ind <- Distance_ind %>%
  left_join(id_center, by = "HEX_Tag_ID") %>%
  mutate(
    distance_m = haversine(
      lon1 = Longitude, lat1 = Latitude,
      lon2 = center_lon, lat2 = center_lat
    )
  ) %>%
  select(-center_lon, -center_lat)

两种方法计算结果完全一致,后续新增ID时只要数据中包含该ID在2022-04-21的坐标记录,就会自动匹配对应中心点计算,不需要修改代码参数。

内容的提问来源于stack exchange,提问作者Pepijn95

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 23:51:25