web-dev-qa-db-fra.com

Meilleure façon d’affecter une matrice en R, NULL vs NA?

J'écris du code R pour créer une matrice carrée. Donc, mon approche est la suivante:

  1. Allouer une matrice de la bonne taille
  2. Parcourez chaque élément de ma matrice et remplissez-le avec une valeur appropriée

Ma question est très simple: quel est le meilleur moyen de pré-allouer cette matrice? Jusqu'ici, j'ai deux façons:

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

ou

> 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

Pour autant que je sache, la première méthode est plus concise que la dernière. En outre, le premier remplit la matrice avec des NA, tandis que le dernier est rempli de NULL.

Quelle est la "meilleure" façon de faire cela? Dans ce cas, je définis "mieux" comme "meilleures performances", car il s'agit d'un calcul statistique et cette opération aura lieu avec de grands ensembles de données.

Bien que le premier soit plus concis, il n’est pas aussi époustouflant de comprendre, et j’ai l’impression que cela pourrait aller dans un sens ou dans l’autre.

Aussi, quelle est la différence entre NA et NULL dans R? ? NA et? NULL me disent que "NA" a une longueur de "1" alors que NULL a une longueur de "0" - mais y a-t-il plus ici? Ou une meilleure pratique? Cela affectera la méthode que j'utilise pour créer ma matrice.

33
poundifdef

En cas de doute, testez-vous. La première approche est à la fois plus facile et plus rapide.

> 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 ce qui concerne la différence entre NA et NULL:

Il y a en fait quatre constantes spéciales. 

En outre, il existe quatre constantes spéciales: NULL, NA, Inf et NaN.

NULL est utilisé pour indiquer l'objet vide. NA est utilisé pour les valeurs de données absentes («non disponibles»). Inf désigne l'infini et NaN n'est pas un nombre dans le calcul en virgule flottante IEEE (résultats des opérations respectivement 1/0 et 0/0, par exemple). 

Vous pouvez en savoir plus dans le manuel R sur la définition du langage .

45
Shane

Selon cet article nous pouvons faire mieux que préallouer avec NA en préallouant avec NA_real_. De l'article:

dès que vous attribuez une valeur numérique à l'une des cellules de 'x', vous devez d'abord forcer la matrice à numérique lorsqu'une nouvelle valeur est attribuée. La matrice logique allouée à l'origine a été allouée en vain et ajoute simplement une empreinte mémoire inutile et un travail supplémentaire pour le ramasse-miettes . Au lieu de l'allouer en utilisant NA_real_ (ou NA_integer_ pour les entiers)

Comme recommandé: testons-le.

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 

Et pour les entiers:

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 différence est faible dans mes cas de test, mais c'est là.

4
David Marx
rows<-3
cols<-3    
x<-rep(NA, rows*cols)
x1 <- matrix(x,nrow=rows,ncol=cols)
0
Odysseus Ithaca