plots - ¿Por qué la función diag es tan lenta?
r plot scale (1)
Resumen
A partir de R versión 3.2.1 (World-Famous Astronaut) diag()
ha recibido una actualización. La discusión se movió a r.789695.n4.nabble.com/… donde se observó que c()
elimina los atributos que no son de nombre y puede haber sido el motivo por el cual se colocó allí. Mientras que a algunas personas les preocupaba que la eliminación de c()
causara problemas desconocidos en los objetos parecidos a matrices, Peter Dalgaard descubrió que, "El único caso donde el c()
dentro de diag()
tiene un efecto es donde M[i,j] != M[(i-1)*m+j]
AND c(M)
ensartarán M
en orden de columna mayor, de modo que M[i,j] == c(M)[(i-1)*m+j]
. "
Luke Tierney probó la eliminación de c()
@Frank, y descubrió que no afectaba a CRAN o BIOC, por lo que se implementó para reemplazar c (x) [...] por x [...] en la línea 27 . Esto conduce a aceleraciones relativamente grandes en diag()
. A continuación se muestra una prueba de velocidad que muestra la mejora con la versión de R 3.2.1 de diag()
.
library(microbenchmark)
nc <- 1e4
set.seed(1)
m <- matrix(sample(letters,nc^2,replace=TRUE), ncol = nc)
microbenchmark(diagOld(m),diag(m))
Unit: microseconds
expr min lq mean median uq max neval
diagOld(m) 451189.242 526622.2775 545116.5668 531905.5635 540008.704 682223.733 100
diag(m) 222.563 646.8675 644.7444 714.4575 740.701 1015.459 100
Estaba viendo los puntos de referencia en esta respuesta , y quería compararlos con diag
(usado en una respuesta diferente). Desafortunadamente, parece que diag
tarda años:
nc <- 1e4
set.seed(1)
m <- matrix(sample(letters,nc^2,replace=TRUE), ncol = nc)
microbenchmark(
diag = diag(m),
cond = m[row(m)==col(m)],
vec = m[(1:nc-1L)*nc+1:nc],
mat = m[cbind(1:nc,1:nc)],
times=10)
Comentarios : Probé estos con identical
. Tomé "cond" de una de las respuestas a esta pregunta de tarea . Los resultados son similares con una matriz de enteros, 1:26
lugar de letters
.
Resultados :
Unit: microseconds
expr min lq mean median uq max neval
diag 604343.469 629819.260 710371.3320 706842.3890 793144.019 837115.504 10
cond 3862039.512 3985784.025 4175724.0390 4186317.5260 4312493.742 4617117.706 10
vec 317.088 329.017 432.9099 350.1005 629.460 651.376 10
mat 272.147 292.953 441.7045 345.9400 637.506 706.860 10
Es solo una operación de subconjunto de matrices, así que no sé por qué hay tanto sobrecarga. Mirando dentro de la función, veo algunas comprobaciones y luego c(m)[v]
, donde v
es el mismo vector utilizado en el punto de referencia "vec". Sincronizando estos dos ...
v <- (1:nc-1L)*nc+1:nc
microbenchmark(diaglike=c(m)[v],vec=m[v])
# Unit: microseconds
# expr min lq mean median uq max neval
# diaglike 579224.436 664853.7450 720372.8105 712649.706 767281.5070 931976.707 100
# vec 334.843 339.8365 568.7808 646.799 663.5825 1445.067 100
... parece que he encontrado a mi culpable. Entonces, la nueva variación en mi pregunta es: ¿Por qué hay un c
en diag
aparentemente innecesario y que consume mucho tiempo?