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

88

data.tableles objets ont maintenant un opérateur: =. Qu'est-ce qui différencie cet opérateur de tous les autres opérateurs d'affectation? Aussi, quelles sont ses utilisations, à quel point est-il plus rapide et quand doit-il être évité?

Ari B. Friedman
la source

Réponses:

94

Voici un exemple montrant 10 minutes réduites à 1 seconde (à partir de NEWS sur la page d' accueil ). C'est comme la sous-attribution à un data.framemais 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 l' :=en jqui permet de créer plus 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 à éviter :=! Autre que, à l'intérieur d'une forboucle. Depuis :=apparaît à l'intérieur DT[...], il vient avec la petite surcharge de la [.data.tableméthode; par exemple, l' expédition S3 et vérifier la présence et le type d'arguments tels que i, by, nomatchetc. Donc , pour l' intérieur des forboucles, il y a une faible surcharge, la version directe d' :=appelé set. Voir ?setpour plus de détails et d'exemples. Les inconvénients de setinclude qui idoivent être des numéros de ligne (pas de recherche binaire) et que vous ne pouvez pas combiner avec by. En faisant ces restrictions, vous setpouvez 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
Matt Dowle
la source
26
Merci d'avoir développé ce package. J'ai le sentiment que je vais réviser une grande partie de mon code pour utiliser ce package.
Iterator
1
Sur le chat, on m'a demandé de me demander / de répondre (ce qui est apparemment encouragé ) - cette question est ici
Matt Dowle
4
@MatthewDowle Vous voulez inclure une explication du moment où ne pas utiliser: = et utiliser set () à la place?
Ari
2
@MatthewDowle j'aurais encore +1 si je le pouvais.
Ari
3
@jabberwocky Pas de problème. set(DT, i, "V1", i)définit la "V1"colonne tandis que set(DT, i, colVar, i)définit le nom de la colonne contenue dans la colVarvariable (par exemple si cela a colVar = "V1"été fait plus tôt). Les guillemets indiquent de prendre le nom de la colonne à la lettre plutôt que de rechercher la variable.
Matt Dowle