如何在不同的数据帧中选择特定时间段内的点,然后根据纬度/经度选择这两个点之间的距离
Posted
技术标签:
【中文标题】如何在不同的数据帧中选择特定时间段内的点,然后根据纬度/经度选择这两个点之间的距离【英文标题】:How to select points within a specific time period in different data frames and then the distance between these two points based on lat/long 【发布时间】:2018-09-14 20:36:52 【问题描述】:我想尝试计算一天中不同时间动物之间的距离。每3
分钟收集一次数据。
我想得到 Animal A
并首先通过找到 B
、C
的对应点将其与 Animal B
和 C
进行比较,并且在时间上最接近 A
然后这些之间的米距离
例如:(这是我编造的,所以可能不完全准确)
Animal ID timestamp long lat
a 2017-09-29 11:07:00 173.1975 -44.94617
a 2017-09-29 11:10:08 173.1976 -44.94619
a 2017-09-29 11:26:56 173.1976 -44.94629
b 2017-09-29 11:09:31 173.1975 -44.94620
b 2017-09-29 11:11:11 173.2345 -45.01769
c 2017-09-29 11:10:00 173.1975 -44.94617
c 2017-09-29 11:25:56 173.3790 -44.93702
在上面,对于动物 a,11:07 的第一个点,B
或 C
在此之后的一分钟内都没有一个点 = 输出 NA
。
然后,对于11:10:08
处的动物点,动物b
和c
在一分钟内都有一个点,我想要这两个点和点a 之间的米距离。
等等。
真实数据大约有 30
动物和超过大约 2
周,所以计算量不太大的东西是一个加分项,尽管不是必须的
期望的输出
ref.animal ref.timestamp ref.long ref.lat animal1 animal1.timestamp lag animal1.long animal1.lat animal1.dist
a 2017-09-29 11:07:00 173.1975 -44.94617 b 2017-09-29 11:09:31 151 173.1975 -44.94620 5.43
a 2017-09-29 11:10:08 173.1976 -44.94619 b 2017-09-29 11:09:31 37 173.1975 -44.94620 10.88
a 2017-09-29 11:26:56 173.1976 -44.94629 b 2017-09-29 11:11:11 945 173.2345 -45.01769 21.80
如果我能把它做成一个巨大的数据框,所有的动物都被列为列(例如animal.1;animal.2),这会很棒,但我很高兴将它作为每个动物对的单独数据框运行。
lag = 两个时间戳之间的差异(以秒为单位) dist = 两个纬度/经度点之间的距离
从这里开始,我的目标是标记距离
【问题讨论】:
输出应该是什么样子的? (例如列表、df、...) 所需的输出是一个 df,其列如下 1. 正在研究的动物的 ID(动物 A) 2. A 的时间戳 3. 下一个动物的 ID(动物 B) 4. 最接近的时间戳动物 B 和动物 A 之间的时间点 5. 两点之间的距离(以米为单位) 6. 下一个动物(动物 C)的 ID 等等.. 【参考方案1】:我不明白你是否只想得到a
和其他动物之间的距离。当您想要获取任意一对动物之间的距离时,这是一种可能的解决方案。
算法是这样工作的。
-
将
Animal ID
的级别分散到列中。
制作一个包含每对 Animal ID
列的列表。
对于 2 中列表的每个元素,获取外部差异。 (获取每列中所有可能对的差异)。
获取小于 60 秒的差的索引。
获取索引对应的Animal ID
的坐标。
获取 5 中坐标对之间的米差。
警告
我只尝试过这种情况,即两只动物在 60 秒内仅相距一次,如您的数据所示。但也许你可以从这个开始。如果你能提供你想要的输出,我可以扩展我的答案。
数据
tt <- 'Animal ID, timestamp, long, lat
a, 2017-09-29 11:07:00, 173.1975, -44.94617
a, 2017-09-29 11:10:08, 173.1976, -44.94619
a, 2017-09-29 11:26:56, 173.1976, -44.94629
b, 2017-09-29 11:09:31, 173.1975, -44.94620
b, 2017-09-29 11:11:11, 173.2345, -45.01769
c, 2017-09-29 11:10:00, 173.1975, -44.94617
c, 2017-09-29 11:25:56, 173.3790, -44.93702'
df <- read.table(text = tt, header = T, sep = ',')
df$timestamp <- as.POSIXct(df$timestamp)
将Animal ID
分散到不同的列中
df1 <- df %>% spread(Animal.ID, timestamp)
删除长和纬度列
df2 <- df1[,c(-1,-2)]
制作一个列表,其中包含Animal ID
的每一对可能的列
df2_comb <- combn(colnames(df2), 2, function(x) list(cbind(df2[x[1]], df2[x[2]])))
步骤 4-6
map_dfr(df2_comb, function(x) index = which(abs(sapply(x[,1], 'difftime', x[,2], units = 'secs')) < 60, arr.ind = TRUE);
point1 = c(df1$long[index[2]], df1$lat[index[2]]);
point2 = c(df1$long[index[1]], df1$lat[index[1]]);
names = paste(names(x), collapse = '-');
dist = distm(point1, point2, fun=distVincentyEllipsoid);
time1 = x[index[2],1];
time2 = x[index[1],2];
return(data.frame(names, time1, time2, dist))
)
输出
names time1 time2 dist
1 a-b 2017-09-29 11:10:08 2017-09-29 11:09:31 7.970
2 a-c 2017-09-29 11:10:08 2017-09-29 11:10:00 8.199
3 b-c 2017-09-29 11:09:31 2017-09-29 11:10:00 3.334
names
对应动物对
time1
和 time2
对应行中每对动物相距 60 秒的时间。
dist
是 distVincentyEllipsoid
(我猜是 metres
)。
【讨论】:
谢谢@hpesoj626 这看起来几乎可以满足我的需求或非常接近.. 但是,我现在只是尝试运行它并进入步骤 4-6 并获得了时间的 NA 值1并且只有第一个GPS点的距离??还有警告消息“在 bind_rows(x, .id) 中:不等因子级别:强制转换为字符”和“在 bind_rows(x,.id) 中:绑定字符和因子向量:强制转换为字符向量” 你能发布你想要的输出吗? 编辑了我的问题以包含所需的输出@hpesoj626 .... 另请注意,我已将时间戳在 1 分钟内的要求更改为仅在 TIME 中标记最近的时间戳以上是关于如何在不同的数据帧中选择特定时间段内的点,然后根据纬度/经度选择这两个点之间的距离的主要内容,如果未能解决你的问题,请参考以下文章