Os loops em R são lentos pela mesma razão que qualquer linguagem interpretada é lenta: cada operação carrega consigo uma grande quantidade de bagagem extra.
Observe R_execClosure
emeval.c
(esta é a função chamada para chamar uma função definida pelo usuário). Tem quase 100 linhas de comprimento e executa todos os tipos de operações - criando um ambiente para execução, atribuindo argumentos ao ambiente, etc.
Pense no quanto menos acontece quando você chama uma função em C (empurre args para empilhar, pule, pop args).
É por isso que você obtém tempos como estes (como joran apontou no comentário, não está realmente apply
sendo rápido; é o loop C interno mean
que está sendo rápido. apply
É apenas um código R antigo normal):
A = matrix(as.numeric(1:100000))
Usando um loop: 0,342 segundos:
system.time({
Sum = 0
for (i in seq_along(A)) {
Sum = Sum + A[[i]]
}
Sum
})
Usando soma: incomensuravelmente pequena:
sum(A)
É um pouco desconcertante porque, assintoticamente, o loop é tão bom quanto sum
; não há razão prática para que seja lento; está apenas fazendo mais trabalho extra a cada iteração.
Portanto, considere:
system.time({
I = 0
while (I < 100000) {
10
I = I + 1
}
})
system.time({
I = 0
while (I < 100000) {
((((((((((10))))))))))
I = I + 1
}
})
(Esse exemplo foi descoberto por Radford Neal )
Porque (
em R é um operador e, na verdade, requer uma pesquisa de nome toda vez que você o usa:
> `(` = function(x) 2
> (3)
[1] 2
Ou, em geral, as operações interpretadas (em qualquer idioma) têm mais etapas. Claro, essas etapas também oferecem benefícios: você não poderia fazer esse (
truque em C.
system.time
guerras nas respostas comecem ...