Объединить два набора данных на основе временного интервала в R

#r #merge

#r #объединить

Вопрос:

У меня есть два набора данных.

Набор данных X выглядит следующим образом. Он содержит 30-минутные интервалы торгового дня некоторого фондового индекса, который открывается в 9:30 утра и закрывается в 15:00 вечера для DJ, но в 16:00 вечера для DX. Таким образом, время закрытия может варьироваться в зависимости от тикера.

  Date    Ticker end_time start_time
1997-10-06  DJ  10:00   09:30
1997-10-06  DJ  10:30   10:00
1997-10-06  DJ  11:00   10:30
1997-10-06  DJ  11:30   11:00
1997-10-08  DJ  09:30   15:00
1997-10-08  DJ  10:00   09:30
1997-10-06  DX  10:00   09:30
1997-10-06  DX  10:30   10:00
1997-10-06  DX  11:00   10:30
1997-10-06  DX  11:30   11:00
1997-10-07  DX  14:30   14:00
1997-10-07  DX  15:00   14:30
1997-10-07  DX  15:30   15:00
1997-10-07  DX  16:00   15:30
1997-10-08  DX  09:30   16:00
1997-10-08  DX  10:00   09:30
 

Набор данных Y выглядит следующим образом:

 Date Time Event
1997-10-06  09:30   Event1
1997-10-06  10:30   Event2
1997-10-07  22:00   Event3
1997-10-08  09:00   Event4
1997-10-08  09:30   Event5
1997-10-08  09:30   Event6
 

Моя цель — связать события в Y с X в зависимости от того, происходит ли дата-время события в интервале времени начала / окончания. Мой ожидаемый результат — это что-то (набор данных Z):

 Date    Ticker end_time start_time Event
1997-10-06  DJ  10:00   09:30 Event1
1997-10-06  DJ  10:30   10:00 NA
1997-10-06  DJ  11:00   10:30 Event2
1997-10-06  DJ  11:30   11:00 NA
1997-10-08  DJ  09:30   15:00 Event3,Event4
1997-10-08  DJ  10:00   09:30 Event5,Event6
1997-10-06  DX  10:00   09:30 Event1
1997-10-06  DX  10:30   10:00 NA
1997-10-06  DX  11:00   10:30 Event2
1997-10-06  DX  11:30   11:00 NA
1997-10-07  DX  14:30   14:00 NA
1997-10-07  DX  15:00   14:30 NA
1997-10-07  DX  15:30   15:00 NA
1997-10-07  DX  16:00   15:30 NA
1997-10-08  DX  09:30   16:00 Event3, Event4
1997-10-08  DX  10:00   09:30 Event5,Event6
 

Таким образом, между интервалом может произойти несколько событий. Возможно ли сохранить их в столбце «Событие». Также возможно, что событие происходит после закрытия рынка, которое должно быть сохранено в первом интервале, который происходит после события. Как я могу получить этот ожидаемый результат? Я уже некоторое время думаю, но понятия не имею, с чего начать.

Редактировать: X содержит 400 Тыс. 30-минутных интервалов. Y содержит 40 тыс. событий.

Ответ №1:

Существует множество способов решения проблемы, вот только одно предложение.

Я использую эти наборы данных:

 x <- read.table(text = "Date,Ticker,end_time,start_time
06/10/1997,DJ,10:00,09:30
06/10/1997,DJ,10:30,10:00
06/10/1997,DJ,11:00,10:30
06/10/1997,DJ,11:30,11:00
08/10/1997,DJ,09:30,15:00
08/10/1997,DJ,10:00,09:30
06/10/1997,DX,10:00,09:30
06/10/1997,DX,10:30,10:00
06/10/1997,DX,11:00,10:30
06/10/1997,DX,11:30,11:00
07/10/1997,DX,14:30,14:00
07/10/1997,DX,15:00,14:30
07/10/1997,DX,15:30,15:00
07/10/1997,DX,16:00,15:30
08/10/1997,DX,09:30,16:00
08/10/1997,DX,10:00,09:30
08/10/1997,DX,10:00,09:30", sep =",", header = TRUE, stringsAsFactors =         
  FALSE)

y <- read.table(text = "Date,Time,Event
06/10/1997,09:30,Event1
06/10/1997,10:30,Event2
07/10/1997,22:00,Event3
08/10/1997,09:00,Event4
08/10/1997,09:30,Event5
08/10/1997,09:30,Event6
", sep =",", header = TRUE, stringsAsFactors = FALSE)
 

Я бы начал с объединения и форматирования дат и времени, чтобы их можно было использовать в функциях для проверки, произошло ли событие в этом окне. Предполагая, что у вас есть два фрейма данных с именами x и y в структуре, описанной выше:

 y$date_time <- strptime(paste(y$Time,y$Date),format="%H:%M %d/%m/%Y")
x$start_time_date <- strptime(paste(x$start_time,x$Date),format="%H:%M %d/%m/%Y")
x$end_time_date <- strptime(paste(x$end_time,x$Date),format="%H:%M %d/%m/%Y")
 

Если у вас есть контроль над набором данных по мере его компиляции, то, возможно, было бы проще записать даты начала и окончания таким образом, так как для периодов, которые пересекают дату, выполнение этого таким образом приведет к появлению даты начала, которые находятся после даты окончания. Мы можем редактировать их, просто используя вместо этого дату из предыдущей записи во фрейме данных, предполагая, что она всегда будет в хронологическом порядке и не будет пропущенных периодов. Это немного взлом!:

 #check which entries cross over a date
overnight_idx <- which(x$end_time_date < x$start_time_date)
#replace start date with that of preceding entry in the data frame
x[overnight_idx, 'start_time_date'] <- 
  as.POSIXct(paste(x[overnight_idx, 'start_time'],
                 x[overnight_idx - 1, 'Date']),format="%H:%M %d/%m/%Y", 
            origin = "1970-01-01")
 

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

 checkEvent <- function(x_row){
  y2 <- y[y$date_time>=x_row['start_time_date'] amp;
            y$date_time<x_row['end_time_date'], 'Event']
  if(length(y2)==0){
    y2 <- NA
  }  else if(length(y2)>1){
    y2 <- paste(y2,collapse = ' ')
  }
  return(y2)
}
 

Тогда мы можем просто применить это к x

 x$Event <- apply(x,1,checkEvent)
 

что приведет к следующему (игнорируя столбцы, которые мы создали выше, чтобы они помещались на экране):

 > x[,c('Date','Ticker','end_time','start_time','Event')]
         Date Ticker end_time start_time         Event
1  06/10/1997     DJ    10:00      09:30        Event1
2  06/10/1997     DJ    10:30      10:00          <NA>
3  06/10/1997     DJ    11:00      10:30        Event2
4  06/10/1997     DJ    11:30      11:00          <NA>
5  08/10/1997     DJ    09:30      15:00 Event3 Event4
6  08/10/1997     DJ    10:00      09:30 Event5 Event6
7  06/10/1997     DX    10:00      09:30        Event1
8  06/10/1997     DX    10:30      10:00          <NA>
9  06/10/1997     DX    11:00      10:30        Event2
10 06/10/1997     DX    11:30      11:00          <NA>
11 07/10/1997     DX    14:30      14:00          <NA>
12 07/10/1997     DX    15:00      14:30          <NA>
13 07/10/1997     DX    15:30      15:00          <NA>
14 07/10/1997     DX    16:00      15:30          <NA>
15 08/10/1997     DX    09:30      16:00 Event3 Event4
16 08/10/1997     DX    10:00      09:30 Event5 Event6
17 08/10/1997     DX    10:00      09:30 Event5 Event6
 

Комментарии:

1. Привет, Сэм, в последнем столбце я получаю список. Итак, для первой строки <df[,1] [1 x 1]> вместо Event1 и во второй строке я получаю <df[,1] [0 x 1]> вместо NA . Вы знаете, как я могу это решить?

2. Я предполагаю, что ваш фрейм данных структурирован неправильно — я отредактировал ответ, чтобы предоставить пригодные для использования фреймы данных с теми же данными