2

考虑以下演示数据:

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

如果我用 构建矩阵mtmodel.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()相关功能真的很有必要?

4

2 回答 2

3

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

model.matrix.defaultmodel.frame返回 a 的调用data.frame。在 内model.matrix.default,这个 data.frame 至少被复制了 3 次。

为什么lm使用model.matrix-->lm通常用data.frame,listenvironment作为data参数调用。model.frame并返回 adata.frame确保公式中的项可以通过对 的后续调用找到lm,并且将引用相同的值。

于 2014-02-12T00:19:00.557 回答
1

通常,调用Rprof(默认情况下library(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

因此,大量时间花在检查NAs withna.omit.data.frame和子集data.framewith [.data.frame, withinmodel.frame.default上。时间的比例会因样本量而异n,但对于大样本量会趋于限制。

于 2014-02-12T03:40:59.090 回答