Для цикла для расчета разницы во времени в R - PullRequest
0 голосов
/ 23 января 2019

Я хотел бы рассчитать разницу между временами в R для каждого наблюдения, учитывая, что оно касается прибытия автобусов и расписаний.Пока у меня есть код:

for (i in ida1d$DATA_TRAMA) {
   for (j in horidat$CORD4) {
       if((ida1d$DATA_TRAMA - horidat$CORD4 < ida1d$diff)) {
           ida1d$diff <- ida1d$DATA_TRAMA - horidat$CORD4
       }                    
   }            
}

У меня есть эти кадры данных:

  • ida1d, в котором есть конкретная информация, которую я хочу
  • horidatу которого есть расписания
  • и ida1d$DATA_TRAMA, и horidat$CORD4 в формате POSIXct %Y-m%-%d %H:%M:%S.

Теперь я пытался создать столбец в ida1dТаблица с отличиями.Проблема состоит в том, что для первых нескольких наблюдений он правильно рассчитывает различия, но с определенной точки это не так, число наблюдений для horidat (расписание) равно 75, а для ida1d - 88, я думаю,проблема с вычислениями может быть из-за этого, таким образом, пытаясь приблизиться к проблеме с циклами for, но я думаю, что я что-то упускаю ...

Дата и время для ida1d - это время прибытия автобуса.на автобусной остановке в течение дня:

ida1d$DATA_TRAMA
     [1] 2010-10-01 00:00:08 
         2010-10-01 00:29:45 
         2010-10-01 06:22:56            
         2010-10-01 06:38:55 
         2010-10-01 06:52:41 
         2010-10-01 07:05:08 
         2010-10-01 07:15:17 
         2010-10-01 07:25:14
         2010-10-01 07:38:25 
         2010-10-01 07:44:55 
         2010-10-01 07:54:44
         2010-10-01 08:05:05 
         2010-10-01 08:14:43 
         2010-10-01 08:24:11 
         2010-10-01 08:33:29 
         2010-10-01 08:46:26
         2010-10-01 08:54:40 
         2010-10-01 09:04:34
         2010-10-01 09:14:53 

И это расписание для автобуса (horidat)

horidat$CORD4
 [2] 2010-10-01 00:00:00 
     2010-10-01 00:30:00 
     2010-10-01 06:25:00  
     2010-10-01 06:45:00 
     2010-10-01 07:00:00 
     2010-10-01 07:15:00 
     2010-10-01 07:30:00 
     2010-10-01 07:45:00 
     2010-10-01 07:57:00 
     2010-10-01 08:09:00 
     2010-10-01 08:21:00 
     2010-10-01 08:32:00 
     2010-10-01 08:43:00 
     2010-10-01 08:54:00 
     2010-10-01 09:06:00 
     2010-10-01 09:18:00  

И я могу рассчитать разницу между [1] и[2] как мы можем видеть под результатами [3]:

ida1d$diff
Time differences in secs
 [3]      8    
         -15   
         -124  
         -365   
         -439   
         -592   
         -883 
         -1186 
         -1115 
         -1445  
         -1576  
         -1615  
         -1697  
         -1789  
         -1951  
         -1894  
         -2120  
         -2246 

Как мы можем видеть, все начинается хорошо, а затем ошибается в остальных вычислениях, и это моя проблема, ия хотел получить наименьшее значение разницы, которое должно быть в столбце для каждого наблюдения, возможно, оно использует другие значения и, следовательно, неправильные вычисления, я думаю ...

Ответы [ 2 ]

0 голосов
/ 24 января 2019

Вот подход с использованием пакета fuzzyjoin. Существуют более быстрые подходы, использующие data.table, такие как здесь и здесь , но для меня этот подход легче следовать и облегчает настройку правила сопоставления, если необходимо.

fuzzyjoin::difference_left_join работает как merge в базе R или left_join в dplyr, создавая "соединение" в стиле базы данных между двумя наборами данных. В этом случае он соединяет соответствующие метки времени в ваших двух таблицах. Как «левое» соединение, оно хранит как минимум одну копию каждой строки исходного кадра данных о прибытии и включает одну строку для каждого соответствующего CORD4 запланированных остановок, которые достаточно близки по времени к этому DATA_TRAMA времени. В этом случае, установив max_dist = 15*60, мы получим все запланированные остановки в течение 15 минут (15 минут x 60 секунд) от времени прибытия. Вероятно, это больше совпадений, чем вы хотите (41 достаточно близкое совпадение для 19 времен прибытия), но это оставляет вам некоторую гибкость, чтобы решить, какие запланированные остановки следует привязать к какому фактическому прибытию.

В этом случае, чтобы выбрать ближайшую по времени запланированную остановку, я использую group_by и top_n из dplyr, чтобы сохранить только строку с наименьшей абсолютной разницей времени для каждого прибытия.

edit: добавлена ​​разность со знаком и ограниченное соединение в один столбец library(dplyr); library(fuzzyjoin) ida1d %>% # select() to bring in only CORD4 from horidat difference_left_join(horidat %>% select(CORD4), by = c(DATA_TRAMA = "CORD4"), max_dist = 15*60, distance_col = "abs_dif") %>% # difference_left_join based on absolute differences # add signed difference mutate(difference = DATA_TRAMA - CORD4) %>% # could use filter like this to limit to only late buses: # filter(difference >= 0) %>% group_by(DATA_TRAMA) %>% top_n(-1, wt = difference) %>% ungroup() # A tibble: 19 x 4 DATA_TRAMA CORD4 abs_dif difference <dttm> <dttm> <time> <time> 1 2010-10-01 00:00:08 2010-10-01 00:00:00 8 secs 8 secs 2 2010-10-01 00:29:45 2010-10-01 00:30:00 15 secs -15 secs 3 2010-10-01 06:22:56 2010-10-01 06:25:00 124 secs -124 secs 4 2010-10-01 06:38:55 2010-10-01 06:45:00 365 secs -365 secs 5 2010-10-01 06:52:41 2010-10-01 07:00:00 439 secs -439 secs 6 2010-10-01 07:05:08 2010-10-01 07:00:00 308 secs 308 secs 7 2010-10-01 07:15:17 2010-10-01 07:15:00 17 secs 17 secs 8 2010-10-01 07:25:14 2010-10-01 07:30:00 286 secs -286 secs 9 2010-10-01 07:38:25 2010-10-01 07:45:00 395 secs -395 secs 10 2010-10-01 07:44:55 2010-10-01 07:45:00 5 secs -5 secs 11 2010-10-01 07:54:44 2010-10-01 07:57:00 136 secs -136 secs 12 2010-10-01 08:05:05 2010-10-01 08:09:00 235 secs -235 secs 13 2010-10-01 08:14:43 2010-10-01 08:09:00 343 secs 343 secs 14 2010-10-01 08:24:11 2010-10-01 08:21:00 191 secs 191 secs 15 2010-10-01 08:33:29 2010-10-01 08:32:00 89 secs 89 secs 16 2010-10-01 08:46:26 2010-10-01 08:43:00 206 secs 206 secs 17 2010-10-01 08:54:40 2010-10-01 08:54:00 40 secs 40 secs 18 2010-10-01 09:04:34 2010-10-01 09:06:00 86 secs -86 secs 19 2010-10-01 09:14:53 2010-10-01 09:18:00 187 secs -187 secs Пример данных: ida1d = data.frame(DATA_TRAMA = as.POSIXct( c( "2010-10-01 00:00:08", "2010-10-01 00:29:45", "2010-10-01 06:22:56", "2010-10-01 06:38:55", "2010-10-01 06:52:41", "2010-10-01 07:05:08", "2010-10-01 07:15:17", "2010-10-01 07:25:14", "2010-10-01 07:38:25", "2010-10-01 07:44:55", "2010-10-01 07:54:44", "2010-10-01 08:05:05", "2010-10-01 08:14:43", "2010-10-01 08:24:11", "2010-10-01 08:33:29", "2010-10-01 08:46:26", "2010-10-01 08:54:40", "2010-10-01 09:04:34", "2010-10-01 09:14:53" ) )) horidat = data.frame(CORD4 = as.POSIXct( c( "2010-10-01 00:00:00", "2010-10-01 00:30:00", "2010-10-01 06:25:00", "2010-10-01 06:45:00", "2010-10-01 07:00:00", "2010-10-01 07:15:00", "2010-10-01 07:30:00", "2010-10-01 07:45:00", "2010-10-01 07:57:00", "2010-10-01 08:09:00", "2010-10-01 08:21:00", "2010-10-01 08:32:00", "2010-10-01 08:43:00", "2010-10-01 08:54:00", "2010-10-01 09:06:00", "2010-10-01 09:18:00" ) ))

0 голосов
/ 24 января 2019

Я собирался комментировать, но у меня нет репутации.Ищем несколько точек.

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

В любом случае я в общих чертах обрисую, как мне это подойти.Как правило, вы хотите избежать петель.Вы можете использовать соединения или векторные операции, которые будут более производительными.Решение кажется, что это будет объединение двух фреймов данных с мутацией для создания столбца различий.Дайте мне знать иначе, если это не так!

# install these if you don't have them
library(dplyr)
library(magrittr)

horidat %>%
  xxxx_join(ida1d, on=c('some_column1','some_column2') %>%
  mutate(diff = as.numeric(difftime(DATA_TRAMA, CORD4, units='secs')))

xxxx_join - это подходящее соединение, например left_join.

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