r - 如何使用 data.table 有效地聚合时间和距离窗口?

标签 r data.table gps rolling-computation

我正在模拟研究中使用 GPS 数据,这意味着我所有的小效率低下都会再次困扰我。

更大的问题之一是停止检测算法的实现。第一步是生成候选停靠点,我在其中识别时间和空间上接近的坐标。

这是一些玩具数据:

library(data.table)
gcdist <- function(lat1, lon1, lat2, lon2){
  sqrt((12430*abs(lat1 - lat2)/180)^2 +
         ((24901*abs(lon1 - lon2)/360) * cos((lat1+lat2)/2))^2) 
}

time <- rev(Sys.time() - seq(60, 30*60, 60))
lat <- cumsum(c(55, rnorm(29, 0, sd  = .003)))
lon <- cumsum(c(5.2, rnorm(29, 0, sd  = .003)))
id <- 1:30

dt <-data.table(id, time, time_dup = time, lon, lat)
dt[, time_window := time + 60*3]
setkey(dt, time, time_window)

我目前正在做的事情使用 data.table 中的 foverlap。数据表友好的解决方案是必须的,因为整个数据集接近 8GB。

这不够高效,无法在适当的时间线上运行我的模拟研究,而且也不是很精确。因为我只在三分钟的窗口内查看然后停止,所以我必须找到处理组合它们的方法。

# Current setup
setkey(dt, time, time_window)
temp <- foverlaps(dt, dt, by.y = c("time", "time_window"), by.x = c("time", "time_dup"), type = "within")
temp[, dist := gcdist(lat, lon, i.lat, i.lon)]
temp[dist < .5, within_stop  := TRUE]
temp[, candidate_stop := all(dist < .5), id]
setkey(temp, id)
setkey(dt, id)
dt[temp, candidate_stop := i.candidate_stop]
setkey(temp, i.id)
dt[temp, within_stop := i.within_stop]

这更接近我应该做的事情,但对于 8GB 的​​数据来说太麻烦了。

current_stop <- dt[1, ]  

for (i in seq_len(nrow(dt))) {
  
  dist <- gcdist(current_stop[, lat], current_stop[, lon],
       dt[i, lat], dt[i, lon])
  if(abs(dist) > .5) current_stop <- dt[i]
  dt[i:nrow(dt), stop_id := current_stop[, id]]
}

我有预感 data.table 的滚动连接或 frollapply 对我有用。我不断地阅读这些页面并尝试示例,但我无法完全使其发挥作用。我认为我应该能够滚动应用距离窗口函数,直到距离大于某个截止值,然后重新启动,但如果我能弄清楚如何做到这一点,这会打败我。

最佳答案

我相信这应该会有所帮助,尽管您的 within_stop 变量可能存在一些问题。

dt[dt,
   on = .(time >= time, time_dup <= time_window),
   c("within_stop", "candidate_stop") := {
     within_stop = gcdist(lat, lon, i.lat, i.lon) < 0.5
     .(within_stop = first(within_stop), ## I am least sure about this. 
          candidate_stop = all(within_stop))
   },
   by = .EACHI]

dt

在我的机器上,该数据集的速度大约是该数据集的两倍。我提到 within_stop 因为它可能在每个加入组内有所不同。也就是说,有时它都是真的,而有时它可能是混合的。如果存在多个匹配项,我无法确定 dt[dt, :=] 默认值是什么,尽管我认为它可能是第一个

为了稍微快一点,您可能可以使用 编译的代码您可以在其中通过短路实现 gcdist() ,以便它仅返回 bool 值。这样,您就不必分配距离向量和 bool 向量是否在您的容差范围内。这似乎有效,尽管对于我当前的数据集来说,性能提升很小。

bool gcdist_short_circuit(NumericVector lat, NumericVector lon,double i_lat, double i_lon) {

  bool out = TRUE;

  for (int i = 0; i < lat.size(); i++) {
    if (sqrt(pow(12430*abs(lat[i] - i_lat)/180, 2) + pow((24901*abs(lon[i] - i_lon)/360) * cos((lat[i]+i_lat)/2),2)) >= 0.5) {
       out = FALSE;
       break;
     }
   }
  return(out);
}

关于r - 如何使用 data.table 有效地聚合时间和距离窗口?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65031351/

相关文章:

r - 图形最有用的输出格式是什么?

r - 从多个列向量创建矩阵

Rstudio 服务器找不到 R 安装的正确位置 (ubuntu)

r - R中按列排序最快

java - 验证/输入 GPS 坐标

ios - iOS 后台模式下的 GPS 监控

javascript - RMarkdown : Color single cells in an HTML table based on conditions

r - 如何计算数据集中每个主题的变量

r - 选择 R 中第一个值等于 "x"的组

android - FusedLocationApi.requestLocationUpdates() 在一段时间后停止间隔请求