为什么model.matrix这么慢?

时间:2014-02-11 23:36:47

标签: r matrix lm model.matrix

考虑以下演示数据:

set.seed(1)
n <- 1000000
x1 <- rnorm(n)
x2 <- rnorm(n)
x3 <- rnorm(n)

如果我使用mt构建矩阵model.matrix(),则需要永远:

system.time(mt <- model.matrix(~x1+x2+x3))
usuário   sistema decorrido 
 0.916     0.185     1.135 

但如果我对矩阵做同样的事情,那就很快了:

system.time(mt2 <- matrix(c(rep(1, n), x1, x2, x3), byrow=FALSE, ncol=4))
 usuário   sistema decorrido 
  0.085     0.021     0.105 

为何与众不同? model.matrix()和相关函数真正需要lm()慢的原因是什么?

2 个答案:

答案 0 :(得分:3)

使用debugonce(model.matrix.default),并使用tracemem(data)

model.matrix.default调用model.frame,返回data.frame。在model.matrix.default内,此data.frame至少复制3次。

为什么lm使用model.matrix - &gt;通常使用lmdata.framelist作为environment参数调用datamodel.frame并返回data.frame可确保后续调用lm可以找到公式中的字词,并且会引用相同的值。

答案 1 :(得分:1)

一般情况下,Rproflibrary(utils)中默认情况下应位于search()路径上)的调用将说明函数调用中时间开销的来源:

Rprof("Rprof.out")
m1 <- model.matrix( ~ x1 + x2 + x3)
Rprof(NULL)
summaryRprof("Rprof.out")

> summaryRprof("Rprof.out")
$by.self
                        self.time self.pct total.time total.pct
"model.matrix.default"       0.12    42.86       0.28    100.00
"na.omit.data.frame"         0.06    21.43       0.14     50.00
"[.data.frame"               0.04    14.29       0.08     28.57
"anyDuplicated.default"      0.04    14.29       0.04     14.29
"as.list.data.frame"         0.02     7.14       0.02      7.14

$by.total
                        total.time total.pct self.time self.pct
"model.matrix.default"        0.28    100.00      0.12    42.86
"model.matrix"                0.28    100.00      0.00     0.00
"na.omit.data.frame"          0.14     50.00      0.06    21.43
"model.frame"                 0.14     50.00      0.00     0.00
"model.frame.default"         0.14     50.00      0.00     0.00
"na.omit"                     0.14     50.00      0.00     0.00
"[.data.frame"                0.08     28.57      0.04    14.29
"["                           0.08     28.57      0.00     0.00
"anyDuplicated.default"       0.04     14.29      0.04    14.29
"anyDuplicated"               0.04     14.29      0.00     0.00
"as.list.data.frame"          0.02      7.14      0.02     7.14
"as.list"                     0.02      7.14      0.00     0.00
"vapply"                      0.02      7.14      0.00     0.00

$sample.interval
[1] 0.02

$sampling.time
[1] 0.28

因此,在NA内检查na.omit.data.frame并在data.frame内将[.data.framemodel.frame.default进行分组,花费了大量时间。时间的比例将根据样本大小n而有所不同,但是对于大样本大小会有限制。