如何根据另一个数据框的日期时间对数据框的特定行进行子集化
How to subset specific rows of a dataframe conditioned to the datetime of another dataframe
我有一个数据框 (df1
),其中包含有关特定变量 (df1$Variable.X
) 超时 (df1$Datetime
) 的信息。 df1$Variable.X
的每个值都是代表50s时间间隔的值。 df1$Datetime
表示这 50 秒时间间隔的初始时间。另一方面,我有一个具有特定日期时间 (df2$Datetime
) 的数据框 (df2
)。下面我创建了一个假的例子:
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
考虑到 df2$Datetime
,我想对数据帧 df1
进行子集化。具体来说,我想创建一个名为 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
有人知道怎么做吗?在我的真实案例中,数据框有数千行,所以我需要一种有效的方法来做到这一点。
提前致谢
这是一个 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
的每个组合。
这是一个使用来自 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
数据(注意时区必须一致才能使代码正常工作):
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"))
我有一个数据框 (df1
),其中包含有关特定变量 (df1$Variable.X
) 超时 (df1$Datetime
) 的信息。 df1$Variable.X
的每个值都是代表50s时间间隔的值。 df1$Datetime
表示这 50 秒时间间隔的初始时间。另一方面,我有一个具有特定日期时间 (df2$Datetime
) 的数据框 (df2
)。下面我创建了一个假的例子:
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
考虑到 df2$Datetime
,我想对数据帧 df1
进行子集化。具体来说,我想创建一个名为 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
有人知道怎么做吗?在我的真实案例中,数据框有数千行,所以我需要一种有效的方法来做到这一点。
提前致谢
这是一个 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
的每个组合。
这是一个使用来自 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
数据(注意时区必须一致才能使代码正常工作):
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"))