Скользящее объединение в Data.Table по двум переменным без создания дубликатов - PullRequest
0 голосов
/ 28 сентября 2019

РЕДАКТИРОВАТЬ 30.09.2019: добавлены примеры и измененный код для воспроизводимости.

Я объединяю два разных набора данных транспортной системы.Один (df1) - это расписание, в котором поезда должны находиться на определенной станции, другой (df2) - наблюдения за поездами, проходящими мимо этих станций.Я использую два столбца для соединения: stop_id (id для станции) и метку времени (дата и время, когда поезда должны были или были замечены на станциях).

Подход, который я использую, использует скользящее объединение с Data.Table в R. Это прекрасно работает, за исключением того факта, что всякий раз, когда я создаю объединение, я продолжаю получать дубликаты одного набора данных, иУ меня не может быть этих повторений в объединенном наборе.Кроме того, мне нужно убедиться, что способ слияния выполняется, только наблюдения, которые происходят ПОСЛЕ или ОДНОВРЕМЕННО с расписанием, сопоставляются с правильной отметкой времени расписания.

Код, который я использую:

#DECLARING FUNCTIONS (Two functions according to df1[df2] and df2[df1])

merge_schedule_obs <- function(df1, df2) {
  setDT(df1)
  setDT(df2)
  max_delay <- 3600 # 1-hour max delay for pairing schedule and occurrence
  setkey(df1, stop_id, departure)[, departScheduled:=departure]
  df3 <- df1[df2, roll = max_delay]
  return(df3)
}

merge_schedule_obs2 <- function(df1, df2) {
  setDT(df1)
  setDT(df2)
  max_delay <- 3600 # 1-hour max delay for pairing schedule and occurrence
  setkey(df1, stop_id, departure)[, departObserved:=departure]
  df3 <- df1[df2, roll = -max_delay]
  return(df3)
}

#CREATING SOME SAMPLE DATA (The real dataset is significantly larger. But this example should cover the problem)


#Sample Schedule Data:

df1 <- distinct(data.table(stop_id = as.factor(c("70015","70009", "70003", "70019","70013", "70007", "70019", "70005", "70007", "70019", "70005")),
                           departure = as.POSIXct(c("2019-09-09 06:57:00","2019-09-09 06:57:00", "2019-09-09 06:57:00",
                                                    "2019-09-09 06:54:30","2019-09-09 06:54:00", "2019-09-09 06:55:00",
                                                    "2019-09-09 06:55:30","2019-09-09 06:55:00", "2019-09-09 06:55:10",
                                                    "2019-09-09  06:55:00", "2019-09-09  06:58:00"))))



Out:

    stop_id           departure
 1:   70015 2019-09-09 06:57:00
 2:   70009 2019-09-09 06:57:00
 3:   70003 2019-09-09 06:57:00
 4:   70019 2019-09-09 06:54:30
 5:   70013 2019-09-09 06:54:00
 6:   70007 2019-09-09 06:55:00
 7:   70019 2019-09-09 06:55:30
 8:   70005 2019-09-09 06:55:00
 9:   70007 2019-09-09 06:55:10
10:   70019 2019-09-09 06:55:00
11:   70005 2019-09-09 06:58:00

#Sample Observations Data:

df2 <- distinct(data.table(stop_id = as.factor(c("70013","70009", "70015", "70005", "70005", "70007", "70019")),
                           departure = as.POSIXct(c("2019-09-09 06:57:10","2019-09-09 07:00:17", "2019-09-09 07:00:12",  "2019-09-09  06:58:20", "2019-09-09  06:58:00",
                                                    "2019-09-09 06:57:30", "2019-09-09 06:57:35")))
)

Out:

   stop_id           departure
1:   70013 2019-09-09 06:57:10
2:   70009 2019-09-09 07:00:17
3:   70015 2019-09-09 07:00:12
4:   70005 2019-09-09 06:58:20
5:   70005 2019-09-09 06:58:00
6:   70007 2019-09-09 06:57:30
7:   70019 2019-09-09 06:57:35
#MERGING DATASETS: (Both directions are covered, and the problem shows in both)

merged_df <- distinct(na.omit(merge_schedule_obs(df1,df2))) 

Out:

   stop_id           departure     departScheduled
1:   70005 2019-09-09 06:58:00 2019-09-09 06:58:00
2:   70005 2019-09-09 06:58:20 2019-09-09 06:58:00
3:   70007 2019-09-09 06:57:30 2019-09-09 06:55:10
4:   70009 2019-09-09 07:00:17 2019-09-09 06:57:00
5:   70013 2019-09-09 06:57:10 2019-09-09 06:54:00
6:   70015 2019-09-09 07:00:12 2019-09-09 06:57:00
7:   70019 2019-09-09 06:57:35 2019-09-09 06:55:30

merged_df2 <- distinct(na.omit(merge_schedule_obs2(df2,df1))) 

Out:
    stop_id           departure      departObserved
 1:   70005 2019-09-09 06:55:00 2019-09-09 06:58:00
 2:   70005 2019-09-09 06:58:00 2019-09-09 06:58:00
 3:   70007 2019-09-09 06:55:00 2019-09-09 06:57:30
 4:   70007 2019-09-09 06:55:10 2019-09-09 06:57:30
 5:   70009 2019-09-09 06:57:00 2019-09-09 07:00:17
 6:   70013 2019-09-09 06:54:00 2019-09-09 06:57:10
 7:   70015 2019-09-09 06:57:00 2019-09-09 07:00:12
 8:   70019 2019-09-09 06:54:30 2019-09-09 06:57:35
 9:   70019 2019-09-09 06:55:00 2019-09-09 06:57:35
10:   70019 2019-09-09 06:55:30 2019-09-09 06:57:35

В результате выполнения скользящего объединения с наборами данных df1 и df2 создается дублирующаяся запись расписания на станции 70005 (если я выполняю объединение наоборот df1 [df2, roll =max_delay, ...] дубликаты происходят в наблюдении вместо этого, на станциях 70005 и 70019).По сути, я не могу от них избавиться.Я пробовал варианты с mult (первый, последний) и пытался играть с rollends ... все еще всегда нежелательные дубликаты ...

Как я могу объединить этинаборы данных без дубликатов?

Спасибо!

1 Ответ

0 голосов
/ 30 сентября 2019

Вот решение, которое не требует data.table пакета.Вместо этого мы будем использовать dplyr и fastmatch пакеты.

Библиотеки и входные данные:

library(dplyr)
library(fastmatch)
df1 <- distinct(data.table(stop_id = as.factor(c("70015","70009", "70003", "70019","70013", "70007", "70019", "70005", "70007", "70019", "70005")),
                           departure = as.POSIXct(c("2019-09-09 06:57:00","2019-09-09 06:57:00", "2019-09-09 06:57:00",
                                                    "2019-09-09 06:54:30","2019-09-09 06:54:00", "2019-09-09 06:55:00",
                                                    "2019-09-09 06:55:30","2019-09-09 06:55:00", "2019-09-09 06:55:10",
                                                    "2019-09-09  06:55:00", "2019-09-09  06:58:00"))))

df2 <- distinct(data.table(stop_id = as.factor(c("70013","70009", "70015", "70005", "70005", "70007", "70019")),
                           departure = as.POSIXct(c("2019-09-09 06:57:10","2019-09-09 07:00:17", "2019-09-09 07:00:12",  "2019-09-09  06:58:20", "2019-09-09  06:58:00",
                                                    "2019-09-09 06:57:30", "2019-09-09 06:57:35")))
)

Расположение обоих фреймов данных в порядке возрастания для их последующего связывания:

A <- df1 %>% 
  arrange(stop_id)
B <- df2 %>%   
  arrange(stop_id)

Использование fastmatch для сопоставления stop-id в двух фреймах данных и их объединения:

C <- A[fmatch(B$stop_id,A$stop_id),] %>% 
  cbind(B[,2,drop = F])
colnames(C) <- c("stop_id","departure","departObserved")

Вывод:

> C
    stop_id           departure      departObserved
2     70005 2019-09-09 06:55:00 2019-09-09 06:58:20
2.1   70005 2019-09-09 06:55:00 2019-09-09 06:58:00
4     70007 2019-09-09 06:55:00 2019-09-09 06:57:30
6     70009 2019-09-09 06:57:00 2019-09-09 07:00:17
7     70013 2019-09-09 06:54:00 2019-09-09 06:57:10
8     70015 2019-09-09 06:57:00 2019-09-09 07:00:12
9     70019 2019-09-09 06:54:30 2019-09-09 06:57:35

Надеюсь, это поможет:)

...