Как разбить объект datetime или интервал объекта на минуту за строкой в ​​R - PullRequest
0 голосов
/ 15 июня 2019

У меня есть набор данных с колонкой datetime (начало) и datetime_end. После манипулирования данными я хочу разбить этот интервал по минутам на строку - скажем, если у меня есть этот интервал

datetime                datetime_end          id   disc
2019-03-19 12:47:28     2019-03-19 12:50:37   5-3 start

Я хотел бы разбить его на несколько минут, чтобы получить что-то вроде этого:

    datetime                  id   disc
2019-03-19 12:48:00           5-3 start
2019-03-19 12:49:00           5-3 start
2019-03-19 12:50:00           5-3 start
2019-03-19 12:51:00           5-3 start

Вот фиктивный фрейм данных

df1 <- data.frame(stringsAsFactors=FALSE,
                  datetime = c("2019-03-19T13:26:52Z", "2019-03-19T13:26:19Z",
                               "2019-03-19T13:23:46Z", "2019-03-19T13:22:20Z",
                               "2019-03-19T13:09:56Z", "2019-03-19T13:06:04Z", "2019-03-19T13:05:21Z",
                               "2019-03-19T13:04:37Z", "2019-03-19T12:47:28Z",
                               "2019-03-19T12:46:42Z"),
                  id = c("5-3", "5-3", "5-3", "5-3", "5-3", "5-3", "5-3", "5-3", "5-3",
                         "5-3"),
                  disc = c("car", "stop", "start", "stop", "start", "stop", "start",
                           "stop", "start", "stop")
)

Я пытался использовать функцию lubridate :: interval для создания объекта интервала (интервала перемещения), но я изо всех сил стараюсь разбить его на минуты в строке (как я показал выше). Так что, если кто-то знает решение, я был бы очень признателен.

Вот мой сценарий

library(tidyverse)
library(lubridate)
  df <- df1 %>% 
    mutate(datetime = lubridate::as_datetime(datetime)) %>% 
    arrange(datetime) %>% 
    mutate(datetime_end = lead(datetime), 
           # Create an interval object.
           Travel_Interval = 
             lubridate::interval(start = datetime, end = datetime_end)) %>% 
    filter(!is.na(Travel_Interval)) %>% 
    # select(-Travel_Interval)
    select(datetime,datetime_end , id , disc,Travel_Interval) %>% 
    filter(disc == "start")

Ответы [ 2 ]

2 голосов
/ 15 июня 2019

Я бы использовал purrr::map2() для этого:

# take df1 %>% mutate datetime column to datetime format %>% sort by datetime
# %>% add datetime_end as lead of datetime %>% filter out records with no
# recorded datetime_end %>% mutate to create column 'minute' by using
# purrr::map2 to iterate over each datetime and datetime_end pair and apply the
# following function {create an sequence of datestamps starting at the "minute
# ceiling" of 'start'datetime' and ending at the "minute ceiling" of
# 'datetime_end in one minute intervals} %>% since the resultant column is a
# list, we have to unnest the data
df <- df1 %>% 
  mutate(datetime = as_datetime(datetime)) %>% 
  arrange(datetime) %>% 
  mutate(datetime_end = lead(datetime, n = 1L)) %>% 
  filter(!is.na(datetime_end)) %>% 
  mutate(minute = purrr::map2(datetime, datetime_end, function(start, stop) {
    seq.POSIXt(from = ceiling_date(start, 'minute'), to = ceiling_date(stop, 'minute'), by = 'min')
  })) %>% 
  unnest()

Обратите внимание, однако, что, поскольку вы эффективно сокращаете временных отметок на минутные интервалы, используя некоторую форму округления (принимаяпотолок, в данном случае), вам придется решить, как бороться с граничными случаями.Например: первый запуск disc == "stop" будет иметь последний конец строки с minute == 2019-03-19 12:48:00, но первый ряд последующего disc == "start "_run" будет начинаться с первого ряда также с minute == 2019-03-19 12:48:00:

              datetime  id  disc        datetime_end              minute
1  2019-03-19 12:46:42 5-3  stop 2019-03-19 12:47:28 2019-03-19 12:47:00
2  2019-03-19 12:46:42 5-3  stop 2019-03-19 12:47:28 2019-03-19 12:48:00
3  2019-03-19 12:47:28 5-3 start 2019-03-19 13:04:37 2019-03-19 12:48:00
4  2019-03-19 12:47:28 5-3 start 2019-03-19 13:04:37 2019-03-19 12:49:00
5  2019-03-19 12:47:28 5-3 start 2019-03-19 13:04:37 2019-03-19 12:50:00
6  2019-03-19 12:47:28 5-3 start 2019-03-19 13:04:37 2019-03-19 12:51:00
7  2019-03-19 12:47:28 5-3 start 2019-03-19 13:04:37 2019-03-19 12:52:00
8  2019-03-19 12:47:28 5-3 start 2019-03-19 13:04:37 2019-03-19 12:53:00
9  2019-03-19 12:47:28 5-3 start 2019-03-19 13:04:37 2019-03-19 12:54:00
10 2019-03-19 12:47:28 5-3 start 2019-03-19 13:04:37 2019-03-19 12:55:00
11 2019-03-19 12:47:28 5-3 start 2019-03-19 13:04:37 2019-03-19 12:56:00
12 2019-03-19 12:47:28 5-3 start 2019-03-19 13:04:37 2019-03-19 12:57:00
13 2019-03-19 12:47:28 5-3 start 2019-03-19 13:04:37 2019-03-19 12:58:00
14 2019-03-19 12:47:28 5-3 start 2019-03-19 13:04:37 2019-03-19 12:59:00
15 2019-03-19 12:47:28 5-3 start 2019-03-19 13:04:37 2019-03-19 13:00:00
16 2019-03-19 12:47:28 5-3 start 2019-03-19 13:04:37 2019-03-19 13:01:00
17 2019-03-19 12:47:28 5-3 start 2019-03-19 13:04:37 2019-03-19 13:02:00
18 2019-03-19 12:47:28 5-3 start 2019-03-19 13:04:37 2019-03-19 13:03:00
19 2019-03-19 12:47:28 5-3 start 2019-03-19 13:04:37 2019-03-19 13:04:00
20 2019-03-19 12:47:28 5-3 start 2019-03-19 13:04:37 2019-03-19 13:05:00
21 2019-03-19 13:04:37 5-3  stop 2019-03-19 13:05:21 2019-03-19 13:05:00
22 2019-03-19 13:04:37 5-3  stop 2019-03-19 13:05:21 2019-03-19 13:06:00
1 голос
/ 15 июня 2019
df1 %>% 
  mutate(datetime = lubridate::as_datetime(datetime)) %>% 
  arrange(datetime) %>% 
  mutate(datetime_end = lead(datetime)) %>%
  filter(!is.na(datetime_end)) %>%
  mutate_at(vars(contains("datetime")), ~ round_date(.x + seconds(30), unit = "minute")) %>%
  mutate(diff = time_length(interval(datetime, datetime_end), unit = "minutes")) %>%
  mutate(time = map2(datetime, diff, ~ .x + minutes(seq(0, .y)))) %>%
  unnest(time)

Просто хотел опубликовать это, так как я уже работал над ним - несмотря на хороший ответ уже там.При этом используются lubridate функции time_length и interval для получения последовательности.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...