R中按个体鸟类计算定位时间差结果不符预期的问题
按个体计算海鸟追踪记录时间差的问题
使用track2KBA包的海鸟追踪数据集,想要按track_id(个体鸟类)分组,计算每条定位记录与同个体上一条记录的时间差。运行脚本后得到的结果不符合预期,误以为第一条记录(track_id=69303,11:01:54)与同个体下一条记录的时间差应为6秒,但实际输出未得到该结果。
错误输出示例
track_id date_gmt time_gmt longitude latitude lon_colony lat_colony datetime difference <int> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dttm> <drtn> 1 69303 2012-07-21 11:01:54 -5.73 -16.0 -5.73 -16.0 2012-07-21 11:01:54 NA secs 2 69302 2012-07-21 11:02:00 -5.73 -16.0 -5.73 -16.0 2012-07-21 11:02:00 NA secs 3 69303 2012-07-21 11:03:33 -5.73 -16.0 -5.73 -16.0 2012-07-21 11:03:33 99 secs 4 69302 2012-07-21 11:03:42 -5.73 -16.0 -5.73 -16.0 2012-07-21 11:03:42 102 secs 5 69303 2012-07-21 11:05:13 -5.73 -16.0 -5.73 -16.0 2012-07-21 11:05:13 100 secs 6 69302 2012-07-21 11:05:26 -5.73 -16.0 -5.73 -16.0 2012-07-21 11:05:26 104 secs
用户代码
library(track2KBA) library(tidyverse) library(lubridate) boobies$datetime <- (paste(boobies$date_gmt, boobies$time_gmt)) boobies <- boobies %>% mutate(datetime = lubridate::ymd_hms(datetime)) %>% group_by(track_id) %>% arrange(datetime) %>% mutate(difference = datetime - lag(datetime))
示例数据
boobies <- structure(list(track_id = c(69303L, 69302L, 69303L, 69302L, 69303L, 69302L), date_gmt = c("2012-07-21", "2012-07-21", "2012-07-21", "2012-07-21", "2012-07-21", "2012-07-21"), time_gmt = c("11:01:54", "11:02:00", "11:03:33", "11:03:42", "11:05:13", "11:05:26"), longitude = c(-5.72769, -5.72639, -5.72769, -5.72635, -5.72769, -5.72639), latitude = c(-16.00749, -16.00713, -16.00749, -16.00723, -16.00749, -16.0071), lon_colony = c(-5.73, -5.73, -5.73, -5.73, -5.73, -5.73), lat_colony = c(-16.01, -16.01, -16.01, -16.01, -16.01, -16.01), datetime = c("2012-07-21 11:01:54", "2012-07-21 11:02:00", "2012-07-21 11:03:33", "2012-07-21 11:03:42", "2012-07-21 11:05:13", "2012-07-21 11:05:26")), .internal.selfref = <pointer: (nil)>, row.names = c(NA, 6L), class = c("data.table", "data.frame"))
解决方案
你的代码逻辑其实是正确的,问题出在对数据的误解:
- 第一条记录(行1)的
track_id是69303,下一条同个体记录是行3(11:03:33),两者时间差为99秒,这和输出结果一致,是正确的。 - 你提到的6秒是行1和行2的时间差,但这两条记录属于不同个体(行2的
track_id是69302),所以不会被计算为同个体的时间差。
如果希望输出结果按个体+时间顺序排列,让同个体的记录连续显示,方便查看,可以在管道最后加上ungroup() %>% arrange(track_id, datetime),修改后的代码如下:
library(track2KBA) library(tidyverse) library(lubridate) boobies <- boobies %>% mutate(datetime = lubridate::ymd_hms(paste(date_gmt, time_gmt))) %>% group_by(track_id) %>% arrange(datetime) %>% mutate(difference = datetime - lag(datetime)) %>% ungroup() %>% arrange(track_id, datetime)
运行后输出会按个体分组,同个体的记录按时间排序,结果更直观:
track_id date_gmt time_gmt longitude latitude lon_colony lat_colony datetime difference <int> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dttm> <drtn> 1 69302 2012-07-21 11:02:00 -5.73 -16.0 -5.73 -16.0 2012-07-21 11:02:00 NA secs 2 69302 2012-07-21 11:03:42 -5.73 -16.0 -5.73 -16.0 2012-07-21 11:03:42 102 secs 3 69302 2012-07-21 11:05:26 -5.73 -16.0 -5.73 -16.0 2012-07-21 11:05:26 104 secs 4 69303 2012-07-21 11:01:54 -5.73 -16.0 -5.73 -16.0 2012-07-21 11:01:54 NA secs 5 69303 2012-07-21 11:03:33 -5.73 -16.0 -5.73 -16.0 2012-07-21 11:03:33 99 secs 6 69303 2012-07-21 11:05:13 -5.73 -16.0 -5.73 -16.0 2012-07-21 11:05:13 100 secs
另外,代码里可以直接在mutate中生成datetime,不需要单独先给boobies$datetime赋值,这样更符合tidyverse的风格。
内容的提问来源于stack exchange,提问作者adkane
相关产品推荐
相关产品推荐

