2009-11-16 12 views
31

Estoy escribiendo código R para crear una matriz cuadrada. Así que mi enfoque es:¿La mejor forma de asignar matriz en R, NULL vs NA?

  1. asignar una matriz del tamaño correcto
  2. bucle a través de cada elemento de mi matriz y llenarlo con un valor apropiado

Mi pregunta es muy simple: ¿cuál es la La mejor manera de preasignar esta matriz? Hasta el momento, tengo dos maneras:

> x <- matrix(data=NA,nrow=3,ncol=3) 
> x 
    [,1] [,2] [,3] 
[1,] NA NA NA 
[2,] NA NA NA 
[3,] NA NA NA 

o

> x <- list() 
> length(x) <- 3^2 
> dim(x) <- c(3,3) 
> x 
    [,1] [,2] [,3] 
[1,] NULL NULL NULL 
[2,] NULL NULL NULL 
[3,] NULL NULL NULL 

Por lo que yo puedo ver, el primero es un método más concisa que el segundo. Además, el primero llena la matriz con NA, mientras que el segundo está lleno de NULL.

¿Cuál es la "mejor" forma de hacer esto? En este caso, estoy definiendo "mejor" como "mejor desempeño", porque esto es computación estadística y esta operación se llevará a cabo con grandes conjuntos de datos.

Mientras que el primero es más conciso, no es impresionantemente más fácil de entender, por lo que siento que esto podría ir en cualquier dirección.

Además, ¿cuál es la diferencia entre NA y NULL en R? ? NA y? NULL me dicen que "NA" tiene una longitud de "1" mientras que NULL tiene una longitud de "0" - pero, ¿hay más aquí? ¿O una mejor práctica? Esto afectará qué método utilizo para crear mi matriz.

+1

No preguntado es, ¿por qué desea * bucle * sobre los elementos de su matriz? ¿Es posible que puedas usar una operación vectorizada en su lugar? ¡Esa debería ser tu próxima pregunta aquí! :) – Harlan

+0

@Harlan que es básicamente a lo que me refiero en esta pregunta aquí: http://stackoverflow.com/questions/1719447/outer-equivalent-for-non-vector-lists-in-r. Si tienes una sugerencia, ¡me encantaría escucharla! – poundifdef

Respuesta

44

En caso de duda, pruébelo usted mismo. El primer enfoque es más fácil y más rápido.

> create.matrix <- function(size) { 
+ x <- matrix() 
+ length(x) <- size^2 
+ dim(x) <- c(size,size) 
+ x 
+ } 
> 
> system.time(x <- matrix(data=NA,nrow=10000,ncol=10000)) 
    user system elapsed 
    4.59 0.23 4.84 
> system.time(y <- create.matrix(size=10000)) 
    user system elapsed 
    0.59 0.97 15.81 
> identical(x,y) 
[1] TRUE 

En cuanto a la diferencia entre NA y NULL:

En realidad, hay cuatro constantes especiales.

Además, hay cuatro constantes especiales, NULL, NA, Inf y NaN.

NULL se utiliza para indicar el objeto vacío. NA se utiliza para valores de datos ausentes ("No disponible"). Inf denota infinito y NaN no es un número en el cálculo de punto flotante IEEE (resultados de las operaciones respectivamente 1/0 y 0/0, por ejemplo).

Puede leer más en the R manual on language definition.

+0

eh, tampoco sabía nada sobre system.time. ¡Muchas gracias! – poundifdef

+0

Si vas a comparar los métodos ¿no deberías haber envuelto ambos métodos en una función? Hay gastos generales agregados con la llamada de función. – Dason

+0

@Dason En la práctica, si uno fuera a usar el método más extenso con frecuencia, ¿no estaría probablemente envuelto en una función? Mientras que 'matriz 'permanecería como está. – Gregor

3

De acuerdo con this article podemos hacer mejor que la preasignación con NA mediante la preasignación con NA_real_. Del artículo:

tan pronto como se asigna un valor numérico a cualquiera de las celdas en 'x', primero se debe forzar la matriz a numérica cuando se asigna un nuevo valor. La matriz lógica asignada originalmente se asignó en vano y solo agrega una huella de memoria innecesaria y trabajo adicional para el recolector de basura. En lugar asignarlo mediante NA_real_ (o NA_integer_ para enteros)

Como se recomienda: vamos a probarlo.

testfloat = function(mat){ 
    n=nrow(mat) 
    for(i in 1:n){ 
    mat[i,] = 1.2 
    } 
} 

>system.time(testfloat(matrix(data=NA,nrow=1e4,ncol=1e4))) 
user system elapsed 
3.08 0.24 3.32 
> system.time(testfloat(matrix(data=NA_real_,nrow=1e4,ncol=1e4))) 
user system elapsed 
2.91 0.23 3.14 

Y para los números enteros:

testint = function(mat){ 
    n=nrow(mat) 
    for(i in 1:n){ 
    mat[i,] = 3 
    } 
} 

> system.time(testint(matrix(data=NA,nrow=1e4,ncol=1e4))) 
user system elapsed 
2.96 0.29 3.31 
> system.time(testint(matrix(data=NA_integer_,nrow=1e4,ncol=1e4))) 
user system elapsed 
2.92 0.35 3.28 

La diferencia es pequeña en mis casos de prueba, pero está ahí.

+1

'3' es de clase' numérico' probablemente signifique 3L. Sin embargo, no veo ningún impacto medible en el rendimiento al usar solo NA (incluso si se mide por 20 segundos cada uno y asegurarme de que Gc hace su trabajo) –

0
rows<-3 
cols<-3  
x<-rep(NA, rows*cols) 
x1 <- matrix(x,nrow=rows,ncol=cols) 
Cuestiones relacionadas