Объединить наборы данных на основе сравнения дат в группах - PullRequest
0 голосов
/ 29 сентября 2018

У меня есть два набора данных: «Df_A» и «Df_B»:

Df_A 
     Date     Info A   Info B
9/19/18 23:00     36       48
9/18/18 23:00     47       30
9/17/18 23:00     51       3
8/14/18 23:00     45       16
8/6/18 23:00      37       13
8/5/18 23:00      42       66
7/11/18 23:00     42       53
7/4/18 23:00      38       10

Df_B
Released Info   Event     Value X
9/6/2018 22:30  Event A   51.8
8/6/2018 22:30  Event A   52
7/5/2018 22:30  Event A   50.6
6/6/2018 22:30  Event A   54
9/2/2018 22:30  Event C   48
7/31/2018 22:30 Event C   45
9/4/2018 22:30  Event D   58.7
8/2/2018 22:30  Event D   56.2
7/3/2018 22:30  Event D   57.3
6/4/2018 22:30  Event D   51.1
5/2/2018 22:30  Event D   54.2
4/4/2018 22:30  Event D   59.8
9/3/2018 1:30   Event E   61.8
8/6/2018 1:30   Event E   63
7/2/2018 1:30   Event E   65.2

Оба «Дата» и «Released.info» являются факторами.

У меня есть вектор 'События », который содержит события в« Df_B », которые мне нужно проанализировать, например,

Events <- c("Event A", "Event D")

Для каждого« события »в« Df_B »я хотел бы проверить, является ли« Дата »в« Df_A »больше, чем «Выпущенная информация» в «Df_B».Если это так, я хочу добавить соответствующее значение «Событие A» и «Событие B» к «Df_A».

Требуемый вывод:

Date           Info A   Info B  Event A Event D
9/19/18 23:00   36       48       51.8   58.7
9/18/18 23:00   47       30       51.8   58.7
9/17/18 23:00   51       3        51.8   58.7
8/14/18 23:00   45       16       52     56.2
8/6/18 23:00    37       13       52     56.2
8/5/18 23:00    42       66       50.6   56.2
7/11/18 23:00   42       53       50.6   57.3
7/4/18 23:00    38       10       54     57.3

Например, для 9/19/18 23:00, 9/18/18 23:00 и 9/17/18 23:00 в 'Df_A', ближайшая предыдущая дата в 'Df_B' для группы 'Событие A' - 9/6/2018 22:30.Таким образом, для этих строк мы выбираем значение 51,8 из 'Df_B'.И так далее для всех дат в Df_A, а также для «Событий A» и «Событий B» в «Df_B».

Я хотел бы добавить новые n столбцов в 'Df_A', в этом примере 'Событие A' и 'Событие D', но это может быть больше.

Для этого я былпытаясь создать динамические переменные для динамического количества событий с чем-то вроде этого (так как события приходят из csv в виде матрицы):

#To Create a variable for each Event
ListEvents <- as.list(as.vector(Events))
names(ListEvents) <- paste("Variable", 1:length(ListEvents), sep = "")
list2env(ListEvents,envir = .GlobalEnv)

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

Ответы [ 2 ]

0 голосов
/ 29 сентября 2018

Это можно сделать с помощью группового объединения по группам в data.table.

library(data.table)

# convert data to data.table
setDT(Df_A)
setDT(Df_B)

# convert times to POSIXct
Df_A[ , Date := as.POSIXct(Date, format = "%m/%d/%y %H:%M")]
Df_B[ , Released.Info := as.POSIXct(Released.Info, format = "%m/%d/%Y %H:%M")]

# select rows
db <- Df_B[Event %in% Events]

# rolling join: for each Event in db, join to Df_A by nearest preceeding time
d2 <- db[ , .SD[Df_A, on = c(Released.Info = "Date"), roll = Inf], by = Event]

#       Event       Released.Info Value.X Info.A Info.B
#  1: Event A 2018-09-19 23:00:00    51.8     36     48
#  2: Event A 2018-09-18 23:00:00    51.8     47     30
# [snip]
#  7: Event A 2018-07-11 23:00:00    50.6     42     53
#  8: Event A 2018-07-04 23:00:00    54.0     38     10
#  9: Event D 2018-09-19 23:00:00    58.7     36     48
# 10: Event D 2018-09-18 23:00:00    58.7     47     30
# [snip]
# 15: Event D 2018-07-11 23:00:00    57.3     42     53
# 16: Event D 2018-07-04 23:00:00    57.3     38     10

Вот и все.Если хотите, увеличьте ширину столбца «Событие» и присоединитесь к «Df_A»:

dcast(d2[ , .(Event, Released.Info, Value.X)],
      Released.Info ~ Event, value.var = "Value.X")[
        Df_A, on = c(Released.Info = "Date")]

#          Released.Info Event A Event D Info.A Info.B
# 1: 2018-09-19 23:00:00    51.8    58.7     36     48
# 2: 2018-09-18 23:00:00    51.8    58.7     47     30
# 3: 2018-09-17 23:00:00    51.8    58.7     51      3
# 4: 2018-08-14 23:00:00    52.0    56.2     45     16
# 5: 2018-08-06 23:00:00    52.0    56.2     37     13
# 6: 2018-08-05 23:00:00    50.6    56.2     42     66
# 7: 2018-07-11 23:00:00    50.6    57.3     42     53
# 8: 2018-07-04 23:00:00    54.0    57.3     38     10
0 голосов
/ 29 сентября 2018

Следующий результат воспроизводит ваш ожидаемый результат:

events <- c("Event A", "Event D")
library(tidyverse)
library(lubridate)
map(events, ~Df_A %>%
    mutate(Event := .x) %>%
    left_join(Df_B) %>%
    mutate(
        Date = mdy_hm(Date),
        Released.Info = mdy_hm(Released.Info)) %>%
        group_by(Date) %>%
        mutate(diff = difftime(Released.Info, Date, units = "days")) %>%
        filter(diff < 0) %>%
        filter(diff == max(diff)) %>%
        select(-Released.Info, -diff) %>%
        spread(Event, Value.X)) %>%
    reduce(left_join) %>%
    arrange(desc(Date))
## A tibble: 8 x 5
## Groups:   Date [8]
#  Date                Info.A Info.B `Event A` `Event D`
#  <dttm>               <int>  <int>     <dbl>     <dbl>
#1 2018-09-19 23:00:00     36     48      51.8      58.7
#2 2018-09-18 23:00:00     47     30      51.8      58.7
#3 2018-09-17 23:00:00     51      3      51.8      58.7
#4 2018-08-14 23:00:00     45     16      52        56.2
#5 2018-08-06 23:00:00     37     13      52        56.2
#6 2018-08-05 23:00:00     42     66      50.6      56.2
#7 2018-07-11 23:00:00     42     53      50.6      57.3
#8 2018-07-04 23:00:00     38     10      54        57.3

Идея состоит в том, чтобы добавить Events столбец к Df_A с записями, данными в векторе events;затем мы выполняем левое объединение Df_A и Df_B и выбираем только те строки с наименьшей отрицательной разницей во времени между Released.Info и Date (это части filter(diff < 0) и filter(diff == max(diff))).Все остальное перестраивается и перестраивается для воспроизведения ожидаемого результата.


Пример данных

Df_A <-read.table(text =
    "     Date        'Info A'  'Info B'
'9/19/18  23:00'    36       48
'9/18/18  23:00'    47       30
'9/17/18  23:00'    51       3
'8/14/18  23:00'    45       16
'8/6/18   23:00'    37       13
'8/5/18   23:00'    42       66
'7/11/18  23:00'    42       53
'7/4/18   23:00'    38       10", header = T)

Df_B <- read.table(text  =
    "'Released Info'   Event     'Value X'
'9/6/2018 22:30'  'Event A'   51.8
'8/6/2018 22:30'  'Event A'   52
'7/5/2018 22:30'  'Event A'   50.6
'6/6/2018 22:30'  'Event A'   54
'9/2/2018 22:30'  'Event C'   48
'7/31/2018 22:30' 'Event C'   45
'9/4/2018 22:30'  'Event D'   58.7
'8/2/2018 22:30'  'Event D'   56.2
'7/3/2018 22:30'  'Event D'   57.3
'6/4/2018 22:30'  'Event D'   51.1
'5/2/2018 22:30'  'Event D'   54.2
'4/4/2018 22:30'  'Event D'   59.8
'9/3/2018 1:30'   'Event E'   61.8
'8/6/2018 1:30'   'Event E'   63
'7/2/2018 1:30'   'Event E'   65.2", header = T)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...