Почему 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 ответа

Решение

С помощью debugonce(model.matrix.default)и в рамках этого использования tracemem(data)

model.matrix.default звонки model.frame который возвращает data.frame, В model.matrix.default, этот data.frame копируется как минимум 3 раза.

Почему lm использование model.matrix -> lm обычно вызывается с data.frame, list или же environment как data аргумент. model.frame и возвращая data.frame гарантирует, что термины в формуле могут быть найдены при последующих вызовах lmи будет ссылаться на те же значения.

В общем, звонок в 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.frame, в model.frame.default, Пропорции времени будут варьироваться в зависимости от размера выборки. n, но будет стремиться к пределу для больших размеров выборки.

Другие вопросы по тегам