web-dev-qa-db-fra.com

Attribuer une valeur à des colonnes et des lignes data.table spécifiques

je comprends toujours ce grand paquet ... Quelqu'un pourrait-il s'il vous plaît m'expliquer la raison de cette erreur? Merci!

library(data.table)

DT <- data.table(id   = LETTERS,
                 var1 = rnorm(26),
                 var2 = rnorm(26))

> DT[2, list(var1, var2)]
            var1          var2
1: -0.8628479332 -0.2367492928
> DT[2, c(var1, var2)]
[1] -0.8628479332 -0.2367492928
> 
> DT[2, list(var1, var2)] <- DT[8, list(var1, var2)]
Error in `[<-.data.table`(`*tmp*`, 2, list(var1, var2), value = list(var1 = -0.394006912428776,  : 
  object 'var1' not found
> DT[2, c(var1, var2)] <- DT[8, c(var1, var2)]
Error in `[<-.data.table`(`*tmp*`, 2, c(var1, var2), value = c(-0.394006912428776,  : 
  object 'var1' not found
19
Michele

Tout d'abord, il est recommandé d'utiliser := Au lieu de [<- Pour plus d'efficacité. Le [<- Est principalement fourni pour la cohérence descendante. Donc, je vais d'abord illustrer comment utiliser efficacement := Pour obtenir ce que vous recherchez. := Est une affectation par référence (et il met à jour une data.table sans copier les données, donc extrêmement rapidement).

require(data.table)
DT <- data.table(x = 1:5, y = 6:10, z = 11:15)

Supposons que vous souhaitiez remplacer la 2ème ligne de "y" par celle de la 5ème ligne de "y":

DT[2, y := DT[5, y]] 

ou équivalent

DT[2, `:=`(y = DT[5, y])]

Supposons que vous souhaitiez remplacer la deuxième ligne de les deux "y" et "z" par celle des entrées correspondantes de la ligne 5, puis:

DT[2, c("y", "z") := as.list(DT[5, c(y, z)])]

ou équivalent

DT[2, `:=`(y = DT[5, y], z = DT[5, z])]

Maintenant, juste pour vous montrer comment attribuer en utilisant [<- (Bien que ce ne soit clairement pas recommandé), cela peut être fait comme suit:

DT <- data.table(x = 1:5, y = 6:10, z = 11:15)
DT[1, c("y", "z")] <- as.list(DT[5, c(y, z)])

ou de manière équivalente, vous pouvez également transmettre le numéro de colonne:

DT[1, 2:3] <- as.list(DT[5, c(y, z)])

J'espère que cela t'aides.


Modifier 1

Quant à savoir pourquoi vous obtenez l'erreur:

Tout d'abord, le RHS doit être une liste pour [<-data.table S'il a plus de 1 colonnes à affecter.

Deuxièmement, l'argument j à gauche de <- N'est pas évalué dans l'environnement de votre data.table. Il a donc besoin de savoir quelles sont les valeurs de j. Et puisque vous fournissez var1 Et var2 (sans les guillemets qui en feraient un vecteur de caractères), il est compris comme une variable. Et donc, il vérifie les variables var1 Et var2, Mais comme il ne "voit" pas les colonnes de votre data.table comme des variables (comme il le fait normalement lorsque vous faites des affectations, etc. le RHS de <-), il cherchera les mêmes variables dans son environnement parent qui est l'environnement global où il ne les trouve pas et ainsi vous obtenez l'erreur. Par exemple: faites ceci:

y <- "y"
z <- "z"
# And now try your second case: 
DT[2, c(y, z)] <- as.list(DT[5, c(y, z)])
# the left side takes values from the assignments you made above
# the right side y and z are evaluated within the environment of your data.table
# and so it sees the columns y and z as variables and their values are picked accordingly

Troisièmement, la fonction [<-data.table N'accepte que les types atomic (vecteur) pour l'argument j. Ainsi, votre première affectation DT[2, list(var1, var2)] <- DT[8, list(var1, var2)] donnera toujours une erreur si vous le faites correctement, c'est-à-dire:

y <- "y"
z <- "z"
DT[2, list(y, z)] <- as.list(DT[5, c(y, z)])

# Error in `[<-.data.table`(`*tmp*`, 2, list(y, z), value = list(10L, 15L)) : 
#   j must be atomic vector, see ?is.atomic

j'espère que cela t'aides.


Modifier 2

Juste pour illustrer qu'une copie de votre data.table est en cours de création lorsque vous faites [<- Mais pas lorsque :=,

DT <- data.table(x = 1:5, y = 6:10, z = 11:15)
tracemem(DT)
# [1] "<0x7fbefb89b580>"

DT[1, c("y", "z") := list(100L, 110L)]
tracemem(DT)
# [1] "<0x7fbefb89b580>"

DT[2, c("y", "z")] <- list(200L, 201L)
# tracemem[0x7fbefacc4fa0 -> 0x7fbefd297838]: # copied, inefficient
35
Arun