Zastąpienie wszystkich brakujących wartości w danych R.tabela z wartością

Jeśli masz dane R.tabela, która ma brakujące wartości, jak zastąpić wszystkie z nich, powiedzmy, wartością 0? Np.

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
Można to zrobić w jednej linii? Gdyby to była tylko matryca, można by po prostu zrobić:
tt[is.na(tt)] = 0
Author: FBC, 2013-12-12

3 answers

is.na (będąc prymitywem) ma stosunkowo niewiele kosztów i zazwyczaj jest dość szybki. Możesz więc po prostu przełączyć kolumny i użyć set, aby zastąpić NA with 0`.

Użycie <-do przypisania spowoduje skopiowanie wszystkich kolumn i nie jest to idiomatyczny sposób użycia data.table.

Najpierw zilustruję, jak to zrobić, a następnie pokażę, jak wolno to może dostać się na ogromne dane (ze względu na kopię):

Jeden sposób, aby to zrobić efektywnie:

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

Otrzymasz tutaj ostrzeżenie, że " 0 " jest zmuszane do znaku, aby pasował do typu kolumny. Możesz to zignorować.

Dlaczego nie powinieneś używać <- tutaj:

# 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
Author: Arun,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-12 23:15:36

Nic niezwykłego tutaj:

tt[is.na(tt)] = 0

..zadziała.

Jest to nieco mylące, jednak biorąc pod uwagę, że:

tt[is.na(tt)]

...aktualnie zwraca:

Błąd w [.data.table (tt, is.na (tt)): I is invalid type (matrix). Być może w przyszłości macierz 2 kolumnowa zwróci listę elementy DT (w duchu A [B] w FAQ 2.14). Proszę pozwól datatable-pomóż dowiedzieć się, czy chcesz, lub dodaj swój komentarz do FR #1611.

 13
Author: thelatemail,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-12 05:50:58

Użyłbym data.table i lapply, czyli:

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

:

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
Author: amonk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-11 23:48:17