Подтвердить что ты не робот

Выберите NA в таблице данных в R

Как выбрать все строки с отсутствующим значением в первичном ключе в таблице данных.

DT = data.table(x=rep(c("a","b",NA),each=3), y=c(1,3,6), v=1:9)
setkey(DT,x)   

Выбор для определенного значения легко

DT["a",]  

Выбор для отсутствующих значений, похоже, требует векторного поиска. Нельзя использовать двоичный поиск. Правильно ли я?

DT[NA,]# does not work
DT[is.na(x),] #does work
4b9b3361

Ответ 1

К счастью, DT[is.na(x),] почти так же быстро, как (например,) DT["a",], поэтому на практике это может не иметь особого значения:

library(data.table)
library(rbenchmark)

DT = data.table(x=rep(c("a","b",NA),each=3e6), y=c(1,3,6), v=1:9)
setkey(DT,x)  

benchmark(DT["a",],
          DT[is.na(x),],
          replications=20)
#             test replications elapsed relative user.self sys.self user.child
# 1      DT["a", ]           20    9.18    1.000      7.31     1.83         NA
# 2 DT[is.na(x), ]           20   10.55    1.149      8.69     1.85         NA

===

Дополнение от Матфея (не вписывается в комментарий):

Приведенные выше данные содержат 3 очень большие группы. Таким образом, преимущество скорости бинарного поиска здесь в настоящее время доминирует для создания большого подмножества (1/3 данных копируется).

benchmark(DT["a",],  # repeat select of large subset on my netbook
    DT[is.na(x),],
    replications=3)
          test replications elapsed relative user.self sys.self
     DT["a", ]            3   2.406    1.000     2.357    0.044
DT[is.na(x), ]            3   3.876    1.611     3.812    0.056

benchmark(DT["a",which=TRUE],   # isolate search time
    DT[is.na(x),which=TRUE],
    replications=3)
                      test replications elapsed relative user.self sys.self
     DT["a", which = TRUE]            3   0.492    1.000     0.492    0.000
DT[is.na(x), which = TRUE]            3   2.941    5.978     2.932    0.004

По мере уменьшения размера возвращаемого подмножества (например, добавления большего числа групп) разница становится очевидной. Векторные сканирование в одном столбце не так уж плохо, но на 2 или более столбцах он быстро ухудшается.

Возможно, NA должны быть присоединены к. Я, кажется, помню, что это было с этим. Здесь некоторая история связана с FR # 1043 Разрешить или запретить NA в ключах?. В нем упоминается, что NA_integer_ внутренне является отрицательным целым числом. Это вызывает сортировку radix/counting (iirc), в результате чего setkey идет медленнее. Но это в списке, чтобы вернуться.

Ответ 2

Это теперь реализовано в версии 1.8.11. Из НОВОСТИ:

o Двоичный поиск теперь может подмножать NA/NaN, а также выполнить joins и merges путем сопоставления NA s/NaN s.

Хотя вам нужно будет указать правильные NA (NA_real_, NA_character_ и т.д.) явно на данный момент.

В данных OP:

DT[J(NA_character_)] # or for characters simply DT[NA_character_]
#     x y v
# 1: NA 1 7
# 2: NA 3 8
# 3: NA 6 9

Кроме того, здесь тот же самый тест из сообщения @JoshOBrien, с этим бинарным поиском для NA добавил:

library(data.table)
library(rbenchmark)

DT = data.table(x=rep(c("a","b",NA),each=3e6), y=c(1,3,6), v=1:9)
setkey(DT,x)  

benchmark(DT["a",],
          DT[is.na(x),],
          DT[NA_character_], 
          replications=20)

            test replications elapsed relative user.self sys.self
1      DT["a", ]           20   4.763    1.238     4.000    0.567
2 DT[is.na(x), ]           20   5.399    1.403     4.537    0.794
3         DT[NA]           20   3.847    1.000     3.215    0.600 # <~~~