我必须经常对data.frame
s序列进行子集化(每次运行数百万次)。 data.frame
的大小约为200行x 30列。根据状态,data.frame
中的值从一次迭代变为下一次迭代。因此,在开头做一个子集是行不通的。
与问题when a data.table starts to be faster than a data.frame相反,我正在寻找加速data.frame
/ data.table
以下最低可重现性示例显示,data.frame
似乎是最快的:
library(data.table)
nmax <- 1e2 # for 1e7 the results look as expected: data.table is really fast!
set.seed(1)
x<-runif(nmax,min=0,max=10)
y<-runif(nmax,min=0,max=10)
DF<-data.frame(x,y)
DT<-data.table(x,y)
summary(microbenchmark::microbenchmark(
setkey(DT,x,y),
times = 10L, unit = "us"))
# expr min lq mean median uq max neval
# 1 setkey(DT, x, y) 70.326 72.606 105.032 80.3985 126.586 212.877 10
summary(microbenchmark::microbenchmark(
DF[DF$x>5, ],
`[.data.frame`(DT,DT$x < 5,),
DT[x>5],
times = 100L, unit = "us"))
# expr min lq mean median uq max neval
# 1 DF[DF$x > 5, ] 41.815 45.426 52.40197 49.9885 57.4010 82.110 100
# 2 `[.data.frame`(DT, DT$x < 5, ) 43.716 47.707 58.06979 53.5995 61.2020 147.873 100
# 3 DT[x > 5] 205.273 214.777 233.09221 222.0000 231.6935 900.164 100
我有什么办法可以改善表现吗?
输入后修改:
data.frame
还是data.table
)。最有可能的是,我可以实现不同的方法,但后来我必须重新编写超过3年开发的代码。目前,这不是一个选择。但如果没有办法让它变得更快,这将成为未来的选择。data.frames
的序列,而是一个data.frame
的序列,它随每次迭代而变化。但是,这对&#34;如何更快地获得子集没有影响&#34;我希望这个问题现在更加全面。答案 0 :(得分:1)
通过转换为矩阵,您将看到性能提升。如果data.frame
的全部内容都是数字(或者可以毫不费力地转换),这是一个可行的选择。
我们走了。首先,我修改了数据,使其大小为200x30:
library(data.table)
nmax = 200
cmax = 30
set.seed(1)
x<-runif(nmax,min=0,max=10)
DF = data.frame(x)
for (i in 2:cmax) {
DF = cbind(DF, runif(nmax,min=0,max=10))
colnames(DF)[ncol(DF)] = paste0('x',i)
}
DT = data.table(DF)
DM = as.matrix(DF) # # # or data.matrix(DF) if you have factors
比较,从最快到最慢排列:
summary(microbenchmark::microbenchmark(
DM[DM[, 'x']>5, ], # # # # Quickest
as.matrix(DF)[DF$x>5, ], # # # # Still quicker with conversion
DF[DF$x>5, ],
`[.data.frame`(DT,DT$x < 5,),
DT[x>5],
times = 100L, unit = "us"))
# expr min lq mean median uq max neval
# 1 DM[DM[, "x"] > 5, ] 13.883 19.8700 22.65164 22.4600 24.9100 41.107 100
# 2 as.matrix(DF)[DF$x > 5, ] 141.100 181.9140 196.02329 195.7040 210.2795 304.989 100
# 3 DF[DF$x > 5, ] 198.846 238.8085 260.07793 255.6265 278.4080 377.982 100
# 4 `[.data.frame`(DT, DT$x < 5, ) 212.342 268.2945 346.87836 289.5885 304.2525 5894.712 100
# 5 DT[x > 5] 322.695 396.3675 465.19192 428.6370 457.9100 4186.487 100
如果您的用例涉及多次查询数据,那么您只能进行一次转换并将速度提高一个数量级。