按时间分组对R数据框行两两组合并计算相关指标的技术问询
解决分组计算探测器配对的Delta与空间距离问题
我来帮你搞定这个分组计算的问题!你已经能处理单个时间戳的情况,现在只需要把逻辑套用到每个时间分组里就行,用Tidyverse的group_modify会比group_map更顺手,因为它能直接帮你合并各分组的结果。下面是完整的解决方案:
第一步:加载所需包
library(dplyr) library(tidyr) library(raster)
第二步:示例数据(和你提供的一致)
bats <- data.frame( time = as.POSIXct(rep(c("2019-05-18 00:00:00","2019-05-18 00:05:00","2019-05-18 00:10:00"),each=3)), device = rep(c("a","b","c"),3), pos.X = rep(c(0,2,4),3), pos.Y = rep(c(5,7,9),3), call.length = rlnorm(9,meanlog=0.5,sd=1) )
第三步:分组计算核心代码
result <- bats %>% # 按时间戳分组,每个时间点单独处理 group_by(time) %>% # 对每个分组应用自定义计算逻辑 group_modify(function(.data, .group) { # 生成当前分组内所有两两行的索引配对(避免重复,只保留idx1 < idx2的组合) row_pairs <- combn(nrow(.data), 2) %>% t() %>% # 转置成行配对的格式 as_tibble(.name_repair = ~c("idx1", "idx2")) # 计算delta、空间距离,同时添加设备配对标识(可选但方便查看) row_pairs %>% mutate( # 计算呼叫时长差的绝对值 delta = abs(.data$call.length[idx1] - .data$call.length[idx2]), # 计算两点间空间距离 distance = raster::pointDistance( p1 = .data[idx1, c("pos.X", "pos.Y")], p2 = .data[idx2, c("pos.X", "pos.Y")], lonlat = FALSE # 这里是平面坐标,所以设为FALSE ), # 添加设备配对名称,方便后续分析 device_pair = paste(.data$device[idx1], .data$device[idx2], sep = "-") ) %>% # 选择最终需要的列,把当前分组的时间戳也带上 select(time = .group, device_pair, delta, distance) }) %>% # 取消分组,得到整洁的结果数据框 ungroup()
代码解释
group_by(time):把数据按时间戳拆分成独立的小组,每个小组对应一个时间点的所有探测器记录。group_modify:对每个分组执行自定义函数,.data代表当前分组的子数据框,.group是当前分组的时间戳值。combn(nrow(.data), 2):生成当前分组内所有两两行的索引对,转置后转换成数据框,避免重复计算(比如a-b和b-a只保留一次)。- 计算
delta时直接通过索引提取对应行的call.length取绝对值差,不用额外拼接数据框。 raster::pointDistance直接传入两行的坐标,简化了之前的坐标拼接步骤。- 最后通过
select整理输出列,确保每个结果行都关联对应的时间戳。
结果预览
你可以用head(result)查看前几行结果,每个时间点会生成3组设备配对(a-b、a-c、b-c),总共9行结果,完全符合你的需求。
内容的提问来源于stack exchange,提问作者AleBru
相关产品推荐
相关产品推荐

