r - 根据从第二个数据集收集的时间间隔对 gps-track 数据集进行子集
问题描述
我有一个大型 gps-track 数据集,我只想提取观察员值班时的位置。换句话说,我需要在观察者正在观看的几个样带中切割 gps 轨迹。观看时段在第二个数据库中,观察者在其中记录(大约每小时)观看时段的开始和结束,因此每天注册的开始时间和结束时间标志着当天的观看时段的开始和结束。在大多数情况下。但是,可能会因为某种原因暂停观看,然后在同一天稍后的某个时间重新开始,因此两个连续的注释之间可能会有时间间隔。
我正在尝试使用 match() 和 dplyr:filter() 函数,但无法找到解决方案。任何想法将不胜感激。
下面是一个简化的例子
DB1(非常大的 gps 跟踪到子集)
date time lat lon
1 18/04/2017 6:10 34.01 -53.07
2 18/04/2017 6:20 34.02 -53.09
3 18/04/2017 6:30 34.04 -53.10
4 18/04/2017 6:40 34.05 -53.11
5 18/04/2017 6:50 34.07 -53.13
6 18/04/2017 7:00 34.08 -53.14
7 18/04/2017 7:10 34.01 -53.07
8 18/04/2017 7:20 34.02 -53.09
9 18/04/2017 7:30 34.04 -53.10
. . . . .
. . . . .
. . . . .
n 19/04/2017 6:10 34.05 -53.11
n+1 19/04/2017 6:20 34.07 -53.13
n+2 19/04/2017 6:30 34.08 -53.14
DB2(观看时段)
date start.watch end.watch
1 2017-04-18 05:00 06:10
2 2017-04-18 06:10 06:30
3 2017-04-18 06:30 06:45
4 2017-04-18 07:20 08:20
. . . .
. . . .
. . . .
n 2017-04-19 06:20 07:20
n+1 2017-04-19 07:20 08:40
结果数据库应该是:`
1 18/04/2017 6:10 34.01 -53.07
2 18/04/2017 6:20 34.02 -53.09
3 18/04/2017 6:30 34.04 -53.10
4 18/04/2017 6:40 34.05 -53.11
8 18/04/2017 7:20 34.02 -53.09
9 18/04/2017 7:30 34.04 -53.10
n 19/04/2017 6:10 34.05 -53.11
n+1 19/04/2017 6:20 34.07 -53.13
n+2 19/04/2017 6:30 34.08 -53.14
解决方案
这是基于时间重叠进行基于范围(模糊)连接的替代方法。它使用data.table::foverlaps
,它确实需要(至少对于此连接)两个框架是正确的data.table
对象,因为它需要明确设置键。
这种方法有几个要求:
- 所有时间戳都可以很容易地在数字上进行比较,我会将它们转换为
POSIXt
对象; - 至少为第二个表设置了键(并且可能对第一个表有所帮助)。每个的最后两个键必须是每个时间间隔的开始和结束;和
- 是的,你没看错,即使是“单次观察”也需要两个时间戳字段。
注意:我magrittr
仅用于将流程分解为各种管道;它根本不是必需的,只是让它更容易阅读。另外,我使用copy()
然后setDT
分配给一个新变量主要是因为(1)我迭代了几次,但每次都想从新数据开始;更重要的是(2),因为data.table
在副作用中运行,我想鼓励你尝试这个但不要杀死你的本地数据,直到你适应它的副作用。data.table
事后你可以很容易地取消它。
首先,我将设置所需的条件。
library(data.table)
library(magrittr)
DB1dt <- copy(DB1) %>%
setDT() %>%
.[, dt := as.POSIXct(paste(date, time), format = "%d/%m/%Y %H:%M") ] %>%
# remove unneeded columns
.[, c("date", "time") := NULL ] %>%
.[, dt2 := dt ] %>%
setkey(dt, dt2)
DB2dt <- copy(DB2) %>%
setDT() %>%
.[, startdt := as.POSIXct(paste(date, start.watch), format = "%Y-%m-%d %H:%M") ] %>%
.[, enddt := as.POSIXct(paste(date, end.watch), format = "%Y-%m-%d %H:%M") - 1e-5 ] %>%
# remove unneeded columns
.[, c("date", "start.watch", "end.watch") := NULL ] %>%
setkey(startdt, enddt)
DB1dt[1:2,]
# lat lon dt dt2
# 1: 34.01 -53.07 2017-04-18 06:10:00 2017-04-18 06:10:00
# 2: 34.02 -53.09 2017-04-18 06:20:00 2017-04-18 06:20:00
DB2dt[1:2,]
# startdt enddt
# 1: 2017-04-18 05:00:00 2017-04-18 06:09:59
# 2: 2017-04-18 06:10:00 2017-04-18 06:29:59
仅供参考:使用-1e-5
是因为“内部”连接在两端都是封闭的([a,b]
与 open-right 形成对比[a,b)
),因此相等性enddt
会匹配。如果你想保留这个,交给你。
从这里开始,重叠连接很简单:
foverlaps(DB1dt, DB2dt, type = "within", nomatch = NULL)
# startdt enddt lat lon dt dt2
# 1: 2017-04-18 06:10:00 2017-04-18 06:29:59 34.01 -53.07 2017-04-18 06:10:00 2017-04-18 06:10:00
# 2: 2017-04-18 06:10:00 2017-04-18 06:29:59 34.02 -53.09 2017-04-18 06:20:00 2017-04-18 06:20:00
# 3: 2017-04-18 06:30:00 2017-04-18 06:44:59 34.04 -53.10 2017-04-18 06:30:00 2017-04-18 06:30:00
# 4: 2017-04-18 06:30:00 2017-04-18 06:44:59 34.05 -53.11 2017-04-18 06:40:00 2017-04-18 06:40:00
# 5: 2017-04-18 07:20:00 2017-04-18 08:19:59 34.02 -53.09 2017-04-18 07:20:00 2017-04-18 07:20:00
# 6: 2017-04-18 07:20:00 2017-04-18 08:19:59 34.04 -53.10 2017-04-18 07:30:00 2017-04-18 07:30:00
# 7: 2017-04-19 06:20:00 2017-04-19 07:19:59 34.07 -53.13 2017-04-19 06:20:00 2017-04-19 06:20:00
# 8: 2017-04-19 06:20:00 2017-04-19 07:19:59 34.08 -53.14 2017-04-19 06:30:00 2017-04-19 06:30:00
样本数据:
DB1 <- read.table(stringsAsFactors = FALSE, header = TRUE, text = "
date time lat lon
18/04/2017 6:10 34.01 -53.07
18/04/2017 6:20 34.02 -53.09
18/04/2017 6:30 34.04 -53.10
18/04/2017 6:40 34.05 -53.11
18/04/2017 6:50 34.07 -53.13
18/04/2017 7:00 34.08 -53.14
18/04/2017 7:10 34.01 -53.07
18/04/2017 7:20 34.02 -53.09
18/04/2017 7:30 34.04 -53.10
19/04/2017 6:10 34.05 -53.11
19/04/2017 6:20 34.07 -53.13
19/04/2017 6:30 34.08 -53.14")
DB2 <- read.table(stringsAsFactors = FALSE, header = TRUE, text = "
date start.watch end.watch
2017-04-18 05:00 06:10
2017-04-18 06:10 06:30
2017-04-18 06:30 06:45
2017-04-18 07:20 08:20
2017-04-19 06:20 07:20
2017-04-19 07:20 08:40")
相关阅读:
推荐阅读
- makefile - 为什么 Makefile 忽略我对 .o 文件的规则?
- java - 删除下载目录中的文件
- android - Hello World 应用程序无法在三星手机上运行
- c - 用于交换字符串的输出相关查询
- typescript - TypeORM RelationCount 替代
- c# - 使用 C# 将 Datatable 转换为嵌套列表/对象
- list - Haskell中的直方图
- java - 洗牌数组背后的逻辑是如何工作的?
- c# - 如何使用 C# 从文档库视图中检索工作簿
- java - java.lang.NumberFormatException:更新 servlet 为 null