Замена всех отсутствующих значений в R data.table со значением

Если у вас есть таблица данных R., у которой отсутствуют значения, как вы их заменяете, скажем, значение 0? Например.

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

Как сделать это в одной строке? Если бы это была просто матрица, вы могли бы просто сделать:

tt[is.na(tt)] = 0

Ответ 1

is.na (являющийся примитивным) имеет относительно немного меньшие накладные расходы и обычно довольно быстро. Таким образом, вы можете просто пропустить столбцы и использовать set для замены NA with 0`.

Использование <- для назначения приведет к копированию всех столбцов, и это не является идиоматическим способом, используя data.table.

Сначала я проиллюстрирую, как это сделать, а затем покажу, как медленно это может получить на огромные данные (из-за копии):

Один из способов сделать это эффективно:

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

Здесь вы получите предупреждение о том, что "0" принуждается к символу в соответствии с типом столбца. Вы можете игнорировать его.

Почему вы не должны использовать <- здесь:

# 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 

Ответ 2

Здесь нет ничего необычного:

tt[is.na(tt)] = 0

.. будет работать.

Это несколько сбивает с толку, учитывая, что:

tt[is.na(tt)]

... теперь возвращает:

Ошибка в [.data.table (tt, is.na(tt)): я недопустимый тип (Матрица). Возможно, в будущем матрица из 2 столбцов может вернуть список элементы DT (в духе A [B] в FAQ 2.14). Пожалуйста, давайте datatable-help знает, хотите ли вы это, или добавьте свои комментарии в FR # 1611.