web-dev-qa-db-fra.com

Quand dois-je utiliser l'opérateur: = dans data.table?

data.table les objets ont maintenant un opérateur: =. Qu'est-ce qui différencie cet opérateur de tous les autres opérateurs d'affectation? De plus, quelles sont ses utilisations, à quel point est-elle plus rapide et quand faut-il l'éviter?

88
Ari B. Friedman

Voici un exemple montrant 10 minutes réduites à 1 seconde (à partir de NEWS sur page d'accueil ). C'est comme une sous-affectation à un data.frame mais ne copie pas la table entière à chaque fois.

m = matrix(1,nrow=100000,ncol=100)
DF = as.data.frame(m)
DT = as.data.table(m)

system.time(for (i in 1:1000) DF[i,1] <- i)
     user  system elapsed 
  287.062 302.627 591.984 

system.time(for (i in 1:1000) DT[i,V1:=i])
     user  system elapsed 
    1.148   0.000   1.158     ( 511 times faster )

Mettre le := dans j comme ça permet plus d'idiomes:

DT["a",done:=TRUE]   # binary search for group 'a' and set a flag
DT[,newcol:=42]      # add a new column by reference (no copy of existing data)
DT[,col:=NULL]       # remove a column by reference

et :

DT[,newcol:=sum(v),by=group]  # like a fast transform() by group

Je ne vois aucune raison d'éviter :=! Autre que, à l'intérieur d'une boucle for. Puisque := apparaît à l'intérieur DT[...], il est livré avec la petite surcharge du [.data.table méthode; par exemple, envoi S3 et vérification de la présence et du type d'arguments tels que i, by, nomatch etc. Donc, pour les boucles internes for, il y a une faible surcharge, une version directe de := appelé set. Voir ?set pour plus de détails et d'exemples. Les inconvénients de set incluent que i doit être un numéro de ligne (pas de recherche binaire) et vous ne pouvez pas le combiner avec by. En faisant ces restrictions, set peut réduire considérablement les frais généraux.

system.time(for (i in 1:1000) set(DT,i,"V1",i))
     user  system elapsed 
    0.016   0.000   0.018
93
Matt Dowle