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
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
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.
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
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