在多个日期范围之间过滤
Filter between multiple date ranges
我有一个大型数据框,两周内每秒进行四次测量。因此数据框非常大。
我还有两个带有开始日期和结束日期的向量,它们定义了数据帧内的某些时间范围,我必须过滤掉这些时间范围。
我想要做的是提取开始日期和结束日期之间的数据。
我的数据看起来像这样。
library(lubridate)
library(dplyr)
df <- data.frame(datetime = seq(ymd_hms("2020/01/01 00:00:00"),
by = "sec",
length.out = 3600),
var = rnorm(3600))
我的 start/end 矢量看起来像这样。这里我只加了两个start/end组合。但实际向量包含更多值。
start = c(ymd_hms("2020/01/01 00:1:00"), ymd_hms("2020/01/01 00:30:00"))
end = c(ymd_hms("2020/01/01 00:1:04"), ymd_hms("2020/01/01 00:30:04"))
我试着过滤它,使用
filtered <- df %>%
filter(datetime >= start & datetime <= end)
head(filtered)
datetime var
1 2020-01-01 00:01:00 -0.2245330
2 2020-01-01 00:01:02 0.5926424
3 2020-01-01 00:01:04 -0.3824533
4 2020-01-01 00:30:01 -0.7202059
5 2020-01-01 00:30:03 -0.5775794
但它似乎对数据进行了下采样,因为过滤后的数据帧在第一个时间间隔内只有三个测量值,而不是预期的五个值。
如果我只筛选第一个开始日期和结束日期,我会得到五个值。
filtered2 <- df %>%
filter(datetime >= start[1] & datetime <= end[1])
head(filtered2)
datetime var
1 2020-01-01 00:01:00 -0.22453305
2 2020-01-01 00:01:01 1.13452854
3 2020-01-01 00:01:02 0.59264239
4 2020-01-01 00:01:03 -0.03700048
5 2020-01-01 00:01:04 -0.38245332
我卡住的地方是:
为什么第一个过滤有效,但没有 return 预期的完整日期范围?
以及如何过滤完整的数据?
我已经试过了 filter(between(datetime, start, end)
。这给了我预期的结果,但仅限于第一个日期范围。 dplyr::between
似乎不接受矢量。
非常欢迎任何帮助。
更新
@ekoam 已正确指出 data.table::between
也有效。但是作为dplyr::between
,它不喜欢向量。
正确的语法是
df %>% filter(dplyr::between(datetime, start[[1L]], end[[1L]]) | dplyr::between(datetime, start[[2L]], end[[2L]]))
更新
我做了以下检查:
res1 <- df %>% filter(data.table::between(datetime, start[[1L]], end[[1L]]) | data.table::between(datetime, start[[2L]], end[[2L]]))
res2 <- df %>% filter(dplyr::between(datetime, start[[1L]], end[[1L]]) | dplyr::between(datetime, start[[2L]], end[[2L]]))
all(res1 == res2)
输出
> all(res1 == res2)
[1] TRUE
因此,如果您还使用 dplyr 1.0.2
和 data.table 1.13.0
,则可以使用 dplyr::between
或 data.table::between
来完成任务。
从这个关于如何 的问题中得到一些启发,我提出了以下解决方案。
一个对于非常大的数据集非常慢:
它采用我上面提供的数据并使用 rowwise()
filtered3 <- df %>%
rowwise() %>%
filter(any(datetime >= start & datetime <= end))
正如我提到的,我的数据中有超过 300 万行,这非常慢。
另一个选项,也来自上面链接的答案,包括使用 data.table 包,它有一个 inrange
功能。这个工作得更快。
library(data.table)
range <- data.table(start = start, end = end)
filtered4 <- setDT(df)[datetime %inrange% range]
我有一个大型数据框,两周内每秒进行四次测量。因此数据框非常大。
我还有两个带有开始日期和结束日期的向量,它们定义了数据帧内的某些时间范围,我必须过滤掉这些时间范围。
我想要做的是提取开始日期和结束日期之间的数据。
我的数据看起来像这样。
library(lubridate)
library(dplyr)
df <- data.frame(datetime = seq(ymd_hms("2020/01/01 00:00:00"),
by = "sec",
length.out = 3600),
var = rnorm(3600))
我的 start/end 矢量看起来像这样。这里我只加了两个start/end组合。但实际向量包含更多值。
start = c(ymd_hms("2020/01/01 00:1:00"), ymd_hms("2020/01/01 00:30:00"))
end = c(ymd_hms("2020/01/01 00:1:04"), ymd_hms("2020/01/01 00:30:04"))
我试着过滤它,使用
filtered <- df %>%
filter(datetime >= start & datetime <= end)
head(filtered)
datetime var
1 2020-01-01 00:01:00 -0.2245330
2 2020-01-01 00:01:02 0.5926424
3 2020-01-01 00:01:04 -0.3824533
4 2020-01-01 00:30:01 -0.7202059
5 2020-01-01 00:30:03 -0.5775794
但它似乎对数据进行了下采样,因为过滤后的数据帧在第一个时间间隔内只有三个测量值,而不是预期的五个值。
如果我只筛选第一个开始日期和结束日期,我会得到五个值。
filtered2 <- df %>%
filter(datetime >= start[1] & datetime <= end[1])
head(filtered2)
datetime var
1 2020-01-01 00:01:00 -0.22453305
2 2020-01-01 00:01:01 1.13452854
3 2020-01-01 00:01:02 0.59264239
4 2020-01-01 00:01:03 -0.03700048
5 2020-01-01 00:01:04 -0.38245332
我卡住的地方是:
为什么第一个过滤有效,但没有 return 预期的完整日期范围?
以及如何过滤完整的数据?
我已经试过了 filter(between(datetime, start, end)
。这给了我预期的结果,但仅限于第一个日期范围。 dplyr::between
似乎不接受矢量。
非常欢迎任何帮助。
更新
@ekoam 已正确指出 data.table::between
也有效。但是作为dplyr::between
,它不喜欢向量。
正确的语法是
df %>% filter(dplyr::between(datetime, start[[1L]], end[[1L]]) | dplyr::between(datetime, start[[2L]], end[[2L]]))
更新
我做了以下检查:
res1 <- df %>% filter(data.table::between(datetime, start[[1L]], end[[1L]]) | data.table::between(datetime, start[[2L]], end[[2L]]))
res2 <- df %>% filter(dplyr::between(datetime, start[[1L]], end[[1L]]) | dplyr::between(datetime, start[[2L]], end[[2L]]))
all(res1 == res2)
输出
> all(res1 == res2)
[1] TRUE
因此,如果您还使用 dplyr 1.0.2
和 data.table 1.13.0
,则可以使用 dplyr::between
或 data.table::between
来完成任务。
从这个关于如何
一个对于非常大的数据集非常慢:
它采用我上面提供的数据并使用 rowwise()
filtered3 <- df %>%
rowwise() %>%
filter(any(datetime >= start & datetime <= end))
正如我提到的,我的数据中有超过 300 万行,这非常慢。
另一个选项,也来自上面链接的答案,包括使用 data.table 包,它有一个 inrange
功能。这个工作得更快。
library(data.table)
range <- data.table(start = start, end = end)
filtered4 <- setDT(df)[datetime %inrange% range]