按时间序列中观察值之间的最小时间间隔提取数据

时间:2019-10-21 06:14:59

标签: r loops datetime dplyr subset

我从动物发射机那里收集了很长的数据。由于发射器太阳能电池的充电量可变,因此数据点之间的间隔高度可变(范围从180秒到一小时以上)。我想对数据进行子集处理,以便点之间的间隔至少为10分钟或600秒。

这是我的一小部分数据的样子:

    datetime             id
    01/09/2015 14:10:54  A
    01/09/2015 14:26:56  A
    01/09/2015 14:41:28  A
    01/09/2015 14:43:53  A
    01/09/2015 14:46:37  A
    01/09/2015 14:48:57  A
    01/09/2015 14:51:31  A
    01/09/2015 14:54:08  A
    04/09/2015 14:37:07  B
    04/09/2015 14:52:07  B
    04/09/2015 15:07:04  B
    04/09/2015 15:15:35  B
    04/09/2015 15:18:00  B
    04/09/2015 15:20:23  B
    04/09/2015 15:22:49  B
    04/09/2015 15:25:12  B 
    04/09/2015 15:28:52  B

我希望的最小间隔为10分钟的输出为:

    datetime             id
    01/09/2015 14:10:54  A
    01/09/2015 14:26:56  A
    01/09/2015 14:41:28  A
    01/09/2015 14:51:31  A
    01/09/2015 14:37:07  B
    04/09/2015 14:52:07  B
    04/09/2015 15:07:04  B
    04/09/2015 15:18:00  B 
    04/09/2015 15:28:52  B

我发现了一个几乎准确的问题,答案为here。他们的数据包括ID,日期和时间。这是答案中给出的代码:

    library(dplyr)
    library(lubridate)

    locdata %>% 
       mutate(timestamp = dmy_hm(paste(date, time))) %>%
       group_by(id, date) %>%
       mutate(delta = timestamp - first(timestamp),
       steps = as.numeric(floor(delta / 3600)), 
       change = ifelse(is.na(steps - lag(steps)), 1, steps - lag(steps))) %>%
          filter(change > 0) %>%
          select(id, date, timestamp)

我对此略作调整,如下所示:

    result <- mydata %>%
                group_by(id) %>%                          
                mutate(delta = datetime - first(datetime),        
                steps = as.numeric(floor(delta / 600)),
                change = ifelse(is.na(steps - lag(steps)), 1, steps - lag(steps)))

代码将显示以下输出:

    datetime             id    delta   steps   change
    01/09/2015 14:10:54  A     0        0      1
    01/09/2015 14:26:56  A     962      1      1
    01/09/2015 14:41:28  A     1834     3      2
    01/09/2015 14:51:31  A     2437     4      1
    04/09/2015 14:37:07  B     0        0      1
    04/09/2015 14:52:07  B     900      1      1
    04/09/2015 15:07:04  B     1797     2      1
    04/09/2015 15:15:35  B     2308     3      1
    04/09/2015 15:18:00  B     2453     4      1
    04/09/2015 15:22:29  B     3105     5      1

输出给出从10点(每个id)开始的每个10分钟时间段的第一个数据点。这并不是我真正需要的,因为某些时间点相距不到10分钟。我需要的是下一次在每个ID内距上一个点 10分钟或更长时间的下一次。

有人知道我该怎么做吗?我需要使用循环吗?谢谢你的想法。

1 个答案:

答案 0 :(得分:0)

我有一个使用dplyr(带有lead()函数)和while循环的想法,它可能对您有帮助

library(dplyr)
library(lubridate)

data <- data %>%
  mutate(date = lubridate::ymd_hms(datetime),
         id_rows = 1:nrow(.)) %>%
  group_by(id) %>%
  mutate(delta = lubridate::time_length(lag(date) %--% date, unit = "sec"))

while (min(data$delta, na.rm = T) < 600) {
  rm_rows <- data %>%
    filter(delta < 600) %>%
    filter(date == min(date)) %>%
    pull(id_rows)
  data <- data %>%
    filter(!id_rows %in% rm_rows) %>%
    mutate(delta = lubridate::time_length(lag(date) %--% date, unit = "sec"))
}