2012-09-13 14 views
10

Tengo un data.table que contiene algunos grupos. Opero en cada grupo y algunos grupos devuelven números, otros devuelven NA. Por alguna razón, data.table tiene problemas para volver a armar todo. ¿Es esto un error o estoy malentendido? He aquí un ejemplo:NA en 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' 

Mi entendimiento es que NA es compatible con los números en R puesto que es evidente que podemos tener una data.table que tiene NA valores. Me doy cuenta de que puedo devolver NULL y que funcionará bien, pero el problema es con NA.

+2

posible duplicado de [¿Por qué el viaje hasta la mediana data.table (entero frente doble)?] (Http: // stackoverflow.com/questions/12125364/why-does-median-trip-up-data-table-integer-versus-double) –

+2

También tuve un problema relacionado una vez: [Dividir una data.table con el by-operator: funciones que devuelven valores numéricos y/o NA fallan] (http://stackoverflow.com/questions/7960798/splitting-a-data-table-with-the-by-operator-functions-that-return-numeric-value) –

+0

@Alex Cuando la pregunta es acerca de un mensaje de error, intente buscar SO para el mensaje de error Por ejemplo [esta búsqueda] (http://stackoverflow.com/search?q=%5Bdata.table%5D+%22columns+of+j+don%27t+evanced+to+consistent+types+for+each+group% 22 & submit = search) devuelve los 2 enlaces anteriores y un 3º también. –

Respuesta

14

De ?NA

NA es una constante lógica de longitud 1, que contiene un indicador de valor que falta. NA puede ser coaccionado a cualquier otro tipo de vector, excepto en bruto. También hay constantes NA_integer_, NA_real_, NA_complex_ y NA_character_ de los otros tipos de vectores atómicos que admiten valores faltantes: todas estas son palabras reservadas en el lenguaje R.

Tendrá que especificar el tipo correcto para su función trabaje -

Puede coaccionar dentro de la función para que coincida con el tipo de x (nótese que necesitamos any para que esto funcione para situaciones con más de 1 fila en un subconjunto!

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

más data.table * * ish enfoque

podría tener sentido más data.table de usar set (o :=) para establecer/reemplazar por referencia.

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

O := dentro [ usando una exploración vector para a==9

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

O := junto con una búsqueda binaria

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

útil señalar

Si utiliza el := o set enfoques, que no parece que tenga que especificar el tipo NA

Tanto el siguiente trabajo

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) 

Esto da un mensaje de error muy útil que le permite saber la razón y la solución:

Error en [.data.table (DTC, J (9), := (a, NA)): Tipo de RHS ('lógico') debe coincidir LHS ('entero'). Controlar y coaccionar afectaría demasiado el rendimiento para los casos más rápidos. Cambie el tipo de la columna de destino o fuerce la RHS de: = usted mismo (p.mediante el uso de 1L en vez de 1)


Lo que es más rápida

con una gran data.set razonable donde a se sustituye in situ

Reemplazar en 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 

Como era de esperar, el enfoque de búsqueda binaria es el más rápido

+0

¡muy interesante! ¿Podrías por favor elaborar un poco? No me di cuenta de que había diferentes tipos de valores 'NA'. – Alex

+0

Aceptaré su respuesta tan pronto como me permita – Alex

+1

Mire'? NA' (citando) * También hay constantes NA_integer_, NA_real_, NA_complex_ y NA_character_ * – mnel

0

también se puede hacer algo como esto:

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

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

El comando anterior le dará la matriz, pero se puede cambiar de nuevo a 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 

Espero que esto ayude.

-1

Si desea asignar AN a muchas variables, se podría utilizar el 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))] 
} 
Cuestiones relacionadas