Gop*_*ala 3 performance r data.table
data.table相当新的.经过两年的抵抗,我终于放弃了我的数据大小.我试图根据滞后时间差(POSIXct)按组计算"等待"时间,如下所示:
dt <- data.table(id = c(rep('a', 5), rep('b', 5)),
time = (Sys.time() + rnorm(10, 100, 10)))
dt <- dt[order(id, time)]
dt[, wait := difftime(time, shift(time, fill = min(time), type = 'lag'),
unit = 'mins'),
by = id]
Run Code Online (Sandbox Code Playgroud)
这工作正常,但是当我在1150万行上运行它有近100,000个组(id)时,它需要大约10s(用户时间和经过时间),其中相同的代码在4500万行上有近200,000个组(id),它需要300多秒的用户时间(超过730秒的经过时间).我用system.time代码周围的命令测量运行时间.
有关为何如此完全非线性扩展性能的想法?而且,我如何通过编写更好的data.table代码来使其线性扩展?
您可以按分组变量对数据进行排序,difftime对整个表进行排序,然后修复每个组的第一行:
ng = 1e5
n = 5L
set.seed(1)
dt <- data.table(
id = rep(1:ng, n),
time = (Sys.time() + rnorm(n*ng, 100, 10)))
setorder(dt, id, time)
system.time(
dt[, wait := difftime(
time,
shift(time, fill = min(time), type = 'lag'),
unit = 'mins'
), by = id][]
)
# user system elapsed
# 8.48 0.00 8.50
system.time({
dt[, wt := difftime(time, shift(time, fill=time[1L]), units='mins')][]
dt[dt[,.I[1L], by=id]$V1, wt := 0][]
})
# user system elapsed
# 0.03 0.00 0.04
Run Code Online (Sandbox Code Playgroud)
比较结果......
dt[wait != wt, summary(as.numeric(abs(wait - wt)))]
# Min. 1st Qu. Median Mean 3rd Qu. Max.
# 3.179e-06 4.140e-05 9.469e-05 9.898e-05 1.274e-04 2.514e-04
dt[, which.min(time), by=id][, table(V1)]
# V1
# 1 2
# 99958 42
Run Code Online (Sandbox Code Playgroud)
结果的微小差异是由于某些四舍五入setorder,但并不是很多,如此处所示.如果你time在第二次使用定义,我猜你根本就不会看到这个.如果你真的需要时间与最短时间,你可以使用setNumericRounding(0)之前setorder.
(正如Arun在评论中提到的,我对你的数据大小做了一些假设.)
| 归档时间: |
|
| 查看次数: |
66 次 |
| 最近记录: |