Соедините два набора данных с ближайшим интервалом времени - PullRequest
3 голосов
/ 21 марта 2019

Я отредактировал свой вопрос - прочитайте вторую часть Редактировать 2

Мне нужно объединить два набора данных с отметкой времени шкафа. Первый набор данных - это набор данных дневника из мобильного приложения:

    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"),
       transport = c("Trainride", "Trainride", "Trainride", "Trainride",
                     "Trainride", "Trainride", "Trainride", "Trainride",
                     "Trainride", "Trainride"),
              id = c("5-3", "5-3", "5-3", "5-3", "5-3", "5-3", "5-3", "5-3", "5-3",
                     "5-3"),
            disc = c("start", "stop", "start", "stop", "start", "stop", "start",
                     "stop", "start", "stop")
    )
 # datetime dttr object   
    df1 <- df1 %>% 
      mutate(datetime = lubridate::as_datetime(datetime))

здесь:

              datetime transport  id  disc
1  2019-03-19 13:26:52 Trainride 5-3 start
2  2019-03-19 13:26:19 Trainride 5-3  stop
3  2019-03-19 13:23:46 Trainride 5-3 start
4  2019-03-19 13:22:20 Trainride 5-3  stop
5  2019-03-19 13:09:56 Trainride 5-3 start
6  2019-03-19 13:06:04 Trainride 5-3  stop
7  2019-03-19 13:05:21 Trainride 5-3 start
8  2019-03-19 13:04:37 Trainride 5-3  stop
9  2019-03-19 12:47:28 Trainride 5-3 start
10 2019-03-19 12:46:42 Trainride 5-3  stop

и второй набор данных - это набор данных из журнала акселерометра, показывающий движение (= INVH) или холостой ход (= NIVH):

df2 <- data.frame(stringsAsFactors=FALSE,
           datetime = c("2019-03-19T23:20:00Z", "2019-03-19T23:17:30Z",
                        "2019-03-19T13:08:00Z", "2019-03-19T13:07:00Z",
                        "2019-03-19T12:38:45Z", "2019-03-19T12:32:45Z",
                        "2019-03-19T11:13:15Z", "2019-03-19T11:11:45Z", "2019-03-19T10:17:45Z",
                        "2019-03-19T10:16:45Z"),
                 id = c("5-3", "5-3", "5-3", "5-3", "5-3", "5-3", "5-3", "5-3", "5-3",
                        "5-3"),
               code = c("NIVH", "INVH", "NIVH", "INVH", "NIVH", "INVH", "NIVH",
                        "INVH", "NIVH", "INVH")
       )
 # datetime dttr object 
df2 <- df2 %>% 
  mutate(datetime = lubridate::as_datetime(datetime))

здесь:

              datetime  id code
1  2019-03-19 23:20:00 5-3 NIVH
2  2019-03-19 23:17:30 5-3 INVH
3  2019-03-19 13:08:00 5-3 NIVH
4  2019-03-19 13:07:00 5-3 INVH
5  2019-03-19 12:38:45 5-3 NIVH
6  2019-03-19 12:32:45 5-3 INVH
7  2019-03-19 11:13:15 5-3 NIVH
8  2019-03-19 11:11:45 5-3 INVH
9  2019-03-19 10:17:45 5-3 NIVH
10 2019-03-19 10:16:45 5-3 INVH

Мне нужно объединить два фрейма данных на основе разницы во времени между полями меток времени. например, оставьте соединение на df1, чтобы увидеть, как данные дневника приложения согласуются с реальным журналом акселерометра. простое соединение слева не будет работать, потому что в большинстве случаев время задержки. Итак, мой квест - как я могу присоединиться к этим двум наборам данных? на основании записи, где разница является минимальной абсолютной разницей.

РЕДАКТИРОВАТЬ 2 --- Решение, предложенное @soren, полезно, однако, если взять интервал времени начала и окончания, оно не будет работать. есть мысли?

df1 <- 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))

1 Ответ

9 голосов
/ 21 марта 2019

Достигается это последовательное соединение, объединяющее фрейм данных к ближайшей дате / времени. Следующее решение с использованием data.table

library(data.table)
dt1 <- as.data.table(df1)
setkeyv(dt1,"datetime")

dt2 <- as.data.table(df2)
setkeyv(dt2,"datetime")
dt2[,nearest_date:=datetime]

dt2[dt1,roll="nearest"]

> dt2[dt1,roll="nearest"]
               datetime  id code        nearest_date transport i.id  disc
 1: 2019-03-19 12:46:42 5-3 NIVH 2019-03-19 12:38:45 Trainride  5-3  stop
 2: 2019-03-19 12:47:28 5-3 NIVH 2019-03-19 12:38:45 Trainride  5-3 start
 3: 2019-03-19 13:04:37 5-3 INVH 2019-03-19 13:07:00 Trainride  5-3  stop
 4: 2019-03-19 13:05:21 5-3 INVH 2019-03-19 13:07:00 Trainride  5-3 start
 5: 2019-03-19 13:06:04 5-3 INVH 2019-03-19 13:07:00 Trainride  5-3  stop
 6: 2019-03-19 13:09:56 5-3 NIVH 2019-03-19 13:08:00 Trainride  5-3 start
 7: 2019-03-19 13:22:20 5-3 NIVH 2019-03-19 13:08:00 Trainride  5-3  stop
 8: 2019-03-19 13:23:46 5-3 NIVH 2019-03-19 13:08:00 Trainride  5-3 start
 9: 2019-03-19 13:26:19 5-3 NIVH 2019-03-19 13:08:00 Trainride  5-3  stop
10: 2019-03-19 13:26:52 5-3 NIVH 2019-03-19 13:08:00 Trainride  5-3 start

Обратите внимание, что добавлен дополнительный столбец "ближайшие_даты" dt2[,nearest_date:=datetime], поэтому при объединении dt2 и dt1 значение даты-времени сохраняется (или доступно для использования для расчета разницы). Принимая во внимание, что объединение / объединение наборов данных по умолчанию возвращает только столбец с первичным ключом. Обычно это желательно, поскольку объединенные столбцы часто идентичны. Здесь, при использовании скользящего объединения, это не так, и полезно сохранить столбец или создать избыточное вручную, как показано здесь.

Обратите внимание также, что ближайшее значение id и datetime также могут иметь отношение к приложению (только одно значение id указано в OP). Это достигается установкой ключей, которые используются в синтаксисе объединения:

setkeyv(dt2,c("id","datetime"))
setkeyv(dt1,c("id","datetime"))
...