web-dev-qa-db-fra.com

Remplacement de toutes les valeurs manquantes dans R data.table par une valeur

Si vous avez un R data.table avec des valeurs manquantes, comment les remplace-t-on toutes avec, par exemple, la valeur 0? Par exemple.

aa = data.table(V1=1:10,V2=c(1,2,2,3,3,3,4,4,4,4))
bb = data.table(V1=3:6,X=letters[1:4])
setkey(aa,V1)
setkey(bb,V1)
tt = bb[aa]

    V1  X V2
 1:  1 NA  1
 2:  2 NA  2
 3:  3  a  2
 4:  4  b  3
 5:  5  c  3
 6:  6  d  3
 7:  7 NA  4
 8:  8 NA  4
 9:  9 NA  4
10: 10 NA  4

Une façon de faire cela en une seule ligne? Si c'était juste une matrice, vous pourriez juste faire:

tt[is.na(tt)] = 0
19
FBC

is.na (étant une primitive) a relativement moins de frais généraux et est généralement assez rapide. Donc, vous pouvez simplement parcourir les colonnes et utiliser set pour remplacer NA with0`.

Utiliser <- pour assigner donnera une copie de all les colonnes et ce n’est pas une façon idiomatique d’utiliser data.table

Je vais d’abord illustrer la procédure à suivre, puis montrer comment lentement ceci peut s’accumuler sur d’énormes données (en raison de la copie):

Une façon de le faire efficacement:

for (i in seq_along(tt)) set(tt, i=which(is.na(tt[[i]])), j=i, value=0)

Vous recevrez un avertissement ici que "0" est contraint à caractère pour correspondre au type de colonne. Vous pouvez l'ignorer.

Pourquoi ne devriez-vous pas utiliser <- ici:

# by reference - idiomatic way
set.seed(45)
tt <- data.table(matrix(sample(c(NA, rnorm(10)), 1e7*3, TRUE), ncol=3))
tracemem(tt)
# modifies value by reference - no copy
system.time({
for (i in seq_along(tt)) 
    set(tt, i=which(is.na(tt[[i]])), j=i, value=0)
})
#   user  system elapsed 
#  0.284   0.083   0.386 

# by copy - NOT the idiomatic way
set.seed(45)
tt <- data.table(matrix(sample(c(NA, rnorm(10)), 1e7*3, TRUE), ncol=3))
tracemem(tt)
# makes copy
system.time({tt[is.na(tt)] <- 0})
# a bunch of "tracemem" output showing the copies being made
#   user  system elapsed 
#  4.110   0.976   5.187 
29
Arun

Rien d'inhabituel ici:

tt[is.na(tt)] = 0

..marchera.

Ceci est toutefois quelque peu déroutant étant donné que:

tt[is.na(tt)]

... retourne actuellement:

Erreur dans [.data.table (tt, is.na (tt)): i est de type non valide (Matrice). Peut-être qu'à l'avenir une matrice à deux colonnes pourrait renvoyer une liste de Éléments de DT (dans l'esprit de A [B] dans FAQ 2.14). S'il vous plaît, laissez Datatable-help savoir si vous le souhaitez, ou ajoutez vos commentaires au FR # 1611.

13
thelatemail

Je voudrais utiliser data.table et lapply, à savoir:

tt[,lapply(.SD,function(kkk) ifelse(is.na(kkk),-666,kkk)),.SDcols=names(tt)]

cédant à: 

V1    X V2
 1:  1 -666  1
 2:  2 -666  2
 3:  3    a  2
 4:  4    b  3
 5:  5    c  3
 6:  6    d  3
 7:  7 -666  4
 8:  8 -666  4
 9:  9 -666  4
10: 10 -666  4
0
amonk