Inner_join с двумя условиями и интервалом в интервале - PullRequest
0 голосов
/ 07 мая 2018

Попытка объединить 2 кадра данных в соответствии с несколькими условиями и условием временного интервала, как в следующем примере:

# two sample dataframes with time intervals
df1 <- data.frame(key1 = c("a", "b", "c", "d", "e"),
                   key2 = c(1:5),
                   time1 = as.POSIXct(hms::as.hms(c("00:00:15", "00:15:15", "00:30:15", "00:40:15", "01:10:15"))),
                   time2 = as.POSIXct(hms::as.hms(c("00:05:15", "00:20:15", "00:35:15", "00:45:15", "01:15:15")))) %>% 
  mutate(t1 = interval(time1, time2)) %>%
  select(key1, key2, t1)  

df2 <- data.frame(key1 = c("b", "c", "a", "e", "d"),
                   key2 = c(2, 6, 1, 8, 5),
                   sam1 = as.POSIXct(hms::as.hms(c("00:21:15", "00:31:15", "00:03:15", "01:20:15", "00:43:15"))),
                   sam2 = as.POSIXct(hms::as.hms(c("00:23:15", "00:34:15", "00:04:15", "01:25:15", "00:44:15")))) %>% 
mutate(t2 = interval(sam1, sam2)) %>%
select(key1, key2, t2)

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

df <- inner_join(df1, df2, by = c("key1", "key2"))

Но есть еще одно условие, которое необходимо проверить при присоединении, и это если интервал t2 находится в пределах t1. Я могу сделать это вручную так:

 df$t2 %within% df$t1

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

# desired dataframe
df <- data.frame(key1 = c("a", "b"), key2 = c(1,2), time_condition = c(TRUE, FALSE))

Если t1 от "00:00:15" to "00:05:15", то соответствующий t2, равный "00:03:15" to "00:04:15", будет находиться в интервале t1. Это приведет к появлению столбца time_condition, который будет TRUE, если t2 находится в пределах t1, и FALSE в противном случае.

Ответы [ 3 ]

0 голосов
/ 07 мая 2018

Используя data.table, вы можете выполнять операции при присоединении. Вот пример

library(data.table)
df2[df1, # left join
    .(time_condition = sam1 > time1 & sam2 < time2), # condition while joining
    on = .(key1, key2), # keys
    by = .EACHI, # check condition per join
    nomatch = 0L] # make it an inner join

#    key1 key2 time_condition
# 1:    a    1           TRUE
# 2:    b    2          FALSE

# your data generated using data.table

df1 <- data.table(key1 = c("a", "b", "c", "d", "e"),
                  key2 = c(1:5),
                  time1 = as.ITime(c("00:00:15", "00:15:15", "00:30:15", "00:40:15", "01:10:15")),
                  time2 = as.ITime(c("00:05:15", "00:20:15", "00:35:15", "00:45:15", "01:15:15"))) 
df2 <- data.table(key1 = c("b", "c", "a", "e", "d"),
                  key2 = c(2, 6, 1, 8, 5),
                  sam1 = as.ITime(c("00:21:15", "00:31:15", "00:03:15", "01:20:15", "00:43:15")),
                  sam2 = as.ITime(c("00:23:15", "00:34:15", "00:04:15", "01:25:15", "00:44:15")))
0 голосов
/ 07 мая 2018

Вы можете использовать встроенную функцию merge () для соединений.

df =  merge(df1, df2, by = c("key1", "key2"))
df = data.frame(df[,c("key1", "key2")], time_condition = df$t2 %within% df$t1)
df
#  key1 key2 time_condition
#1    a    1           TRUE
#2    b    2          FALSE

Спасибо

0 голосов
/ 07 мая 2018

Как насчет этого?

library(dplyr)

df1 %>%
  inner_join(df2, by = c("key1", "key2")) %>%
  filter(sam1 >= time1 & sam1 <= time2 & sam2 >= time1 & sam2 <= time2) %>%
  mutate(t1 = interval(time1, time2),
         t2 = interval(sam1, sam2)) %>%
  select(key1, key2, t1, t2)

Вывод:

  key1 key2                                               t1                                               t2
1    a    1 1970-01-01 00:00:15 UTC--1970-01-01 00:05:15 UTC 1970-01-01 00:03:15 UTC--1970-01-01 00:04:15 UTC

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

df1 <- data.frame(key1 = c("a", "b", "c", "d", "e"),
                  key2 = c(1:5),
                  time1 = as.POSIXct(hms::as.hms(c("00:00:15", "00:15:15", "00:30:15", "00:40:15", "01:10:15"))),
                  time2 = as.POSIXct(hms::as.hms(c("00:05:15", "00:20:15", "00:35:15", "00:45:15", "01:15:15"))))

df2 <- data.frame(key1 = c("b", "c", "a", "e", "d"),
                  key2 = c(2, 6, 1, 8, 5),
                  sam1 = as.POSIXct(hms::as.hms(c("00:21:15", "00:31:15", "00:03:15", "01:20:15", "00:43:15"))),
                  sam2 = as.POSIXct(hms::as.hms(c("00:23:15", "00:34:15", "00:04:15", "01:25:15", "00:44:15"))))
...