2012-09-13 21 views
10

Mam data.table, który zawiera niektóre grupy. Operuję na każdej grupie, a niektóre grupy zwracają numery, inne zwracają NA. Z jakiegoś powodu data.table ma problemy ze złożeniem wszystkiego razem. Czy to błąd, czy też nieporozumienie? Oto przykład:NA w data.table

dtb <- data.table(a=1:10) 
f <- function(x) {if (x==9) {return(NA)} else { return(x)}} 
dtb[,f(a),by=a] 

Error in `[.data.table`(dtb, , f(a), by = a) : 
    columns of j don't evaluate to consistent types for each group: result for group 9 has  column 1 type 'logical' but expecting type 'integer' 

Moje zrozumienie, że NA jest zgodna z numerami w R ponieważ wyraźnie możemy mieć data.table że ma NA wartości. Rozumiem, że mogę zwrócić NULL, a to zadziała dobrze, ale problem jest z NA.

+2

możliwe duplikat [Dlaczego mediana utrącają data.table (całkowita kontra podwójnej)?] (Http: // stackoverflow.com/questions/12125364/why-does-median-trip-up-data-table-integer-versus-double) –

+2

Miałem również podobny problem: [Dzielenie tabeli danych na osobny operator: funkcje, które zwracają wartości numeryczne i/lub NA nie działają] (http://stackoverflow.com/questions/7960798/splitting-a-data-table-w--operator-functions-that-return-numeric-value) –

+0

@Alex Gdy pytanie dotyczy komunikatu o błędzie, spróbuj wyszukać SO dla komunikatu o błędzie. Na przykład [to wyszukiwanie] (http://stackoverflow.com/search?q=%5Bdata.table%5D+%22columns+of+j+don%27t+ocenę+do+konsystentnych+typów+do+each+grupy% 22 & submit = search) zwraca 2 linki powyżej i 3 także. –

Odpowiedz

14

Od ?NA

NA jest logicznym stały o długości 1, który zawiera wskaźnik wartości brakującego. NA może być wymuszony na dowolny inny typ wektora z wyjątkiem surowego. Istnieją również stałe NA_integer_, NA_real_, NA_complex_ i NA_character_ z innych typów wektorów atomowych, które obsługują brakujące wartości: wszystkie z nich są słowami zarezerwowanymi w języku R.

Trzeba będzie określić właściwy typ dla czynność do pracy -

można przymusić wewnątrz funkcji, aby dopasować rodzaj x (uwaga musimy any dla tej pracy w sytuacjach, z więcej niż 1 wiersz w podgrupie!

f <- function(x) {if any((x==9)) {return(as(NA, class(x)))} else { return(x)}} 

więcej data.table * * ish podejście

To może uczynić więcej data.table sensu używać set (lub :=), aby ustawić/zastąpić przez odniesienie.

set(dtb, i = which(dtb[,a]==9), j = 'a', value=NA_integer_) 

Albo := ciągu [ stosując skanowanie wektora dla a==9

dtb[a == 9, a := NA_integer_] 

Or := wraz z binarne wyszukiwania

setkeyv(dtb, 'a') 
dtb[J(9), a := NA_integer_] 

przydatna pamiętać

Jeśli używasz := lub set podejścia, nie wydają się konieczne, aby określić typ NA

oba poniższe zadziała

dtb <- data.table(a=1:10) 
setkeyv(dtb,'a') 
dtb[a==9,a := NA] 

dtb <- data.table(a=1:10) 
setkeyv(dtb,'a') 
set(dtb, which(dtb[,a] == 9), 'a', NA) 

Daje to bardzo użyteczne komunikat o błędzie, który pozwala poznać przyczynę i rozwiązanie:

błąd [.data.table (dTC, J (9) := (a, nA)): Rodzaj RHS ('logiczny') musi być zgodna z LHS ('całkowita'). Sprawdzanie i przymuszanie wpłynęłoby zbytnio na wydajność w najszybszych przypadkach. Zmień typ kolumny docelowej lub wymusić na RHS: = yourself (np.stosując 1 litr zamiast 1)


które jest najszybszym

z wystarczającą dużą data.set gdzie a otrzymuje się in situ

wymienić in situ

library(data.table) 

set.seed(1) 
n <- 1e+07 
DT <- data.table(a = sample(15, n, T)) 
setkeyv(DT, "a") 
DTa <- copy(DT) 
DTb <- copy(DT) 
DTc <- copy(DT) 
DTd <- copy(DT) 
DTe <- copy(DT) 

f <- function(x) { 
    if (any(x == 9)) { 
     return(as(NA, class(x))) 
    } else { 
     return(x) 
    } 
} 

system.time({DT[a == 9, `:=`(a, NA_integer_)]}) 
## user system elapsed 
## 0.95 0.24 1.20 
system.time({DTa[a == 9, `:=`(a, NA)]}) 
## user system elapsed 
## 0.74 0.17 1.00 
system.time({DTb[J(9), `:=`(a, NA_integer_)]}) 
## user system elapsed 
## 0.02 0.00 0.02 
system.time({set(DTc, which(DTc[, a] == 9), j = "a", value = NA)}) 
## user system elapsed 
## 0.49 0.22 0.67 
system.time({set(DTc, which(DTd[, a] == 9), j = "a", value = NA_integer_)}) 
## user system elapsed 
## 0.54 0.06 0.58 
system.time({DTe[, `:=`(a, f(a)), by = a]}) 
## user system elapsed 
## 0.53 0.12 0.66 
# The are all the same! 
all(identical(DT, DTa), identical(DT, DTb), identical(DT, DTc), identical(DT, 
    DTd), identical(DT, DTe)) 
## [1] TRUE 

Nieoczekiwanie podejście do wyszukiwania binarnego jest najszybsze:

+0

interesujące! czy mógłbyś trochę rozwinąć? nie zdawałem sobie sprawy, że istnieją różne typy wartości "NA" .. – Alex

+0

Przyjmę odpowiedź, gdy tylko pozwoli mi – Alex

+1

Spójrz na "? NA" (cytując) * Istnieją również stałe NA_integer_, NA_real_, NA_complex_ i NA_character_ * – mnel

0

można też zrobić coś takiego:

dtb <- data.table(a=1:10) 

mat <- ifelse(dtb == 9,NA,dtb$a) 

Powyższa komenda da Ci matrycy, ale można go zmienić z powrotem do data.table

new.dtb <- data.table(mat) 
new.dtb 
    a 
1: 1 
2: 2 
3: 3 
4: 4 
5: 5 
6: 6 
7: 7 
8: 8 
9: NA 
10: 10 

nadzieję, że to pomaga.

-1

Jeśli chcesz przypisać NAS wielu zmiennych, można użyć approach suggested here:

v_1 <- c(0,0,1,2,3,4,4,99) 
v_2 <- c(1,2,2,2,3,99,1,0) 
dat <- data.table(v_1,v_2) 

for(n in 1:2) { 
    chari <- paste0(sprintf('v_%s' ,n), ' %in% c(0,99)') 
    charj <- sprintf('v_%s := NA_integer_', n) 
    dat[eval(parse(text=chari)), eval(parse(text=charj))] 
}