我正在与R-Studio合作,并希望从data.table中获取多行。
假设我有一个data.table,其中包含以下数据:
Date Column 1
"01.02.2016 10:00:00 CEST" 10
"01.02.2016 10:01:00 CEST" 12
"01.02.2016 10:02:00 CEST" 13
"01.02.2016 10:03:00 CEST" 11
"01.02.2016 10:04:00 CEST" 17
并且我想要从“ 01.02.2016 10:00:30”到“ 01.02.2016 10:02:30”的值是这样的:
Date Column 1
"01.02.2016 10:01:00 CEST" 12
"01.02.2016 10:02:00 CEST" 13
目前,我通过执行以下操作来实现此目的:
x <- data.table[Date >= "01.02.2016 10:00:30 CEST" & Date <= "01.02.2016 10:02:30 CEST"]
但这对我来说太慢了,因为在具有60万行的data.table上,它大约需要0.4秒。
相反,这要快得多:
setkey(data.table, Date)
x <- prozessdaten.data.table[J(c("01.02.2016 10:01:00 CEST", "01.02.2016 10:02:00 CEST"))]
我的问题是否有可能在指定的时间范围内而不是确切的值使用二进制搜索函数J()?
data.table v1.9.7 +已实现非等额联接,并添加了一个inrange
使用此新功能并可以实现您想要的功能的新功能
## Loading data
library(data.table) #v 1.9.7+
DT <- data.table(date = c('01.02.2016 10:00:00','01.02.2016 10:01:00',
'01.02.2016 10:02:00','01.02.2016 10:03:00',
'01.02.2016 10:04:00'),
column1 = c(10, 12, 13, 11, 17))
## Converting to POSIXct class
DT[, date := as.POSIXct(date, format = "%d.%m.%Y %H:%M:%S")]
## Validating that forder/bmerge kicks in
options(datatable.verbose = TRUE)
DT[date %inrange% as.POSIXct(c("2016-02-01 10:00:30", "2016-02-01 10:02:30"))]
# forderv(query) took ... 0 secs
# Starting bmerge ...done in 0 secs <~~~~~~~~ (Thanks to @Arun for fixing the bug)
# Generating final logical vector ... done in 0 secs
# date column1
# 1: 2016-02-01 10:01:00 12
# 2: 2016-02-01 10:02:00 13
不过,您应该知道,由于实现了data.table 1.9.4次要键,这意味着对于矢量扫描的某些变化,在第一次运行后会添加一个键,从现在开始,甚至还会使用==
和操作。这似乎在类上不起作用,但是您可以在数字列上观察到此行为%in%
bmerge
POSIXct
column1
## Running for first time
options(datatable.verbose = TRUE)
DT[column1 == 10]
# Creating new index 'column1'
# forder took 0 sec <~~~ forder kicks in, hence first time is a bit slow
# Starting bmerge ...done in 0 secs
# date column1
# 1: 2016-02-01 10:00:00 10
## Running for second time and on
DT[column1 == 10]
# Using existing index 'column1'
# Starting bmerge ...done in 0 secs <~~ bmerge kicks in from now on
# date column1
# 1: 2016-02-01 10:00:00 10
如前所述通过@Jan,这个计划对于非球菌中实现联接也从V2.0.0开始
编辑(26/8/2016):
正如@Arun指出的那样,尽管inrange
使用二进制连接,但它需要首先对整个向量进行排序,以检查x中的每个值是否在上,下提供的任何间隔之间。在您的情况下,这有点麻烦,因为您仅将两个值进行比较,因此最近用Cbetween
函数重写的代码将更适合您
set.seed(123)
DT <- data.table(x = sample(5e8))
system.time(res1 <- DT[x > 1e3L & x < 1e5L])
# user system elapsed
# 10.23 1.22 11.45
system.time(res2 <- DT[x %inrange% c(1e3L, 1e5L)])
# forderv(query) took ... 29.09 secs
# Starting bmerge ...done in 0 secs
# Generating final logical vector ... done in 0.43 secs
# user system elapsed
# 29.28 0.70 30.06
system.time(res3 <- DT[x %between% c(1e3L, 1e5L)])
# user system elapsed
# 2.01 2.60 0.84
因此,您可以看到,尽管bmerge
几乎是即时的,但排序需要花费大量时间。Whilebetween
是最快的,因为它不需要x
两次转换为逻辑向量。哎呀,between
太快了,elapsed
小到了user
+system
不过,如果您的数据已经排序,那么inrange
可以很好地赶上
setorder(DT, x)
system.time(res1 <- DT[x > 1e3L & x < 1e5L])
# user system elapsed
# 10.41 1.02 11.45
system.time(res2 <- DT[x %inrange% c(1e3L, 1e5L)])
# forderv(query) took ... 2.17 secs
# Starting bmerge ...done in 0 secs
# Generating final logical vector ... done in 0.44 secs
# user system elapsed
# 2.47 0.71 3.20
system.time(res3 <- DT[x %between% c(1e3L, 1e5L)])
# user system elapsed
# 2.30 2.62 0.88
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句