Извлечение данных по минимальному временному интервалу между наблюдениями во временном ряду - PullRequest
1 голос
/ 21 октября 2019

У меня очень длинный набор данных, собранных с передатчиков животных. Из-за переменного заряда солнечных батарей передатчика интервал между точками данных сильно варьируется (от 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

Myжелаемый результат с минимальным интервалом в 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

Я нашел почти точный вопрос с ответом здесь . Их данные включали идентификатор, дату и время. Вот код, приведенный в ответе:

    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-минутном временном блоке, начинающемся в нулевое время (для идентификатора). Это не совсем то, что мне нужно, так как некоторые моменты времени находятся на расстоянии менее 10 минут. Что мне нужно, так это в следующий раз, когда 10 минут или больше после предыдущей точки внутри каждого идентификатора.

Есть идеи, как мне это сделать? Нужно ли использовать цикл? Спасибо за любые идеи.

1 Ответ

0 голосов
/ 21 октября 2019

У меня была идея использовать 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"))
}
...