Как указать подмножество c строк кадра данных, привязанных к дате и времени другого кадра данных - PullRequest
1 голос
/ 01 августа 2020

У меня есть один фрейм данных (df1) с информацией об особой c переменной (df1$Variable.X) сверхурочной работе (df1$Datetime). Каждое значение df1$Variable.X представляет собой значение, представляющее интервал времени 50 секунд. df1$Datetime представляет начальное время для этих 50-секундных интервалов. С другой стороны, у меня есть фрейм данных (df2), в котором указано c datetimes (df2$Datetime). Ниже я создаю поддельный пример:

set.seed(123)
df1 <- data.frame(Datetime= seq.POSIXt(as.POSIXct("2017-03-08 11:00:00.001", format="%Y-%m-%d %H:%M:%OS", tz="UTC"), as.POSIXct("2017-03-08 12:15:00.001", format="%Y-%m-%d %H:%M:%OS", tz="UTC"), by = "50 sec", tz="UTC"),
                  Variable.X= sample(x = 1:10, size = 91, replace = TRUE))

df2 <- data.frame(Datetime=c("2017-03-08 11:04:34.546","2017-03-08 11:24:14.646","2017-03-08 11:38:55.098","2017-03-08 11:58:12.023","2017-03-08 12:11:34.546"))


head(df1)
                 Datetime Variable.X
1 2017-03-08 11:00:00.000          5
2 2017-03-08 11:00:50.000         10
3 2017-03-08 11:01:40.000          2
4 2017-03-08 11:02:30.000          2
5 2017-03-08 11:03:20.000          6
6 2017-03-08 11:04:10.000          4

head(df2)
                 Datetime
1 2017-03-08 11:04:34.546
2 2017-03-08 11:24:14.646
3 2017-03-08 11:38:55.098
4 2017-03-08 11:58:12.023
5 2017-03-08 12:11:34.546

Я хотел бы подмножество фрейма данных df1 с учетом df2$Datetime. В частности, я хотел бы создать фрейм данных с именем df1.A, в котором у меня есть строки, для которых df2$Datetime не включен во временной интервал, определяемый df1$Datetime + 50s, и фрейм данных с именем df1.B, в котором у меня есть строки df1, для которого df2$Datetime включен во временной интервал, определяемый df1$Datetime + 50s. Таким образом, nrow (df1.A) + nrow (df1.B) = nrow (df1).

В этом примере df1.B будет:

df1.B
                 Datetime Variable.X
1 2017-03-08 11:04:10.000          5
2 2017-03-08 11:24:10.000          9
3 2017-03-08 11:38:20.000          9
4 2017-03-08 11:57:30.000          3
5 2017-03-08 12:10:50.000          2

Кто-нибудь знает, как сделать это? Фреймы данных в моем реальном случае содержат тысячи строк, поэтому мне понадобится эффективный способ сделать это.

Заранее спасибо

Ответы [ 2 ]

3 голосов
/ 02 августа 2020

Вот вариант, использующий неэквивалентное соединение из data.table и извлечение индексов строк с помощью which=TRUE:

library(data.table)
setDT(df1)[, later := Datetime + 50]
setDT(df2)

ix <- df1[df2, on=.(Datetime<=Datetime, later>Datetime), which=TRUE]
df1.A <- df1[!ix]
df1.B <- df1[ix]

df1.B:

              Datetime Variable.X               later
1: 2017-03-08 11:04:10          5 2017-03-08 11:05:00
2: 2017-03-08 11:24:10          9 2017-03-08 11:25:00
3: 2017-03-08 11:38:20          9 2017-03-08 11:39:10
4: 2017-03-08 11:57:30          3 2017-03-08 11:58:20
5: 2017-03-08 12:10:50          2 2017-03-08 12:11:40

data ( обратите внимание, что часовой пояс должен быть согласован для правильной работы кода):

set.seed(123)
df1 <- data.frame(Datetime= seq.POSIXt(as.POSIXct("2017-03-08 11:00:00.001", format="%Y-%m-%d %H:%M:%OS", tz="UTC"), as.POSIXct("2017-03-08 12:15:00.001", format="%Y-%m-%d %H:%M:%OS", tz="UTC"), by = "50 sec", tz="UTC"),
    Variable.X= sample(x = 1:10, size = 91, replace = TRUE))

df2 <- data.frame(Datetime=as.POSIXct(c("2017-03-08 11:04:34.546","2017-03-08 11:24:14.646","2017-03-08 11:38:55.098","2017-03-08 11:58:12.023","2017-03-08 12:11:34.546"),
    format="%Y-%m-%d %H:%M:%OS", tz="UTC"))
2 голосов
/ 01 августа 2020

Вот способ tidyverse:

library(dplyr)

df2 <- df2 %>% mutate(Datetime = lubridate::ymd_hms(Datetime))
df1.B <- df2 %>% 
          rename(dt = Datetime) %>%
          tidyr::crossing(df1) %>%
          filter(between(difftime(dt, Datetime, units = "secs"), 0, 50))

df1.A <- df1 %>% anti_join(df1.B %>% select(-dt))

df1.B
# A tibble: 5 x 3
#  dt                  Datetime            Variable.X
#  <dttm>              <dttm>                   <int>
#1 2017-03-08 11:04:34 2017-03-08 11:04:10          5
#2 2017-03-08 11:24:14 2017-03-08 11:24:10          9
#3 2017-03-08 11:38:55 2017-03-08 11:38:20          9
#4 2017-03-08 11:58:12 2017-03-08 11:57:30          3
#5 2017-03-08 12:11:34 2017-03-08 12:10:50          2

nrow(df1.A)
#[1] 86
nrow(df1.B)
#[1] 5
nrow(df1)
#[1] 91

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

...