sistema redundancia que lineales inconsistentes inconsistente inconsistencia homogeneo ejemplos ejemplo ecuaciones datos consistente 2x2 r dataframe data.table

redundancia - DT[!(X==.)] Y DT[x!=.] Tratan NA en x inconsistentemente



sistema de ecuaciones lineales 2x2 inconsistente (4)

Esto es algo que pensé que debería preguntar después de esta pregunta . Me gustaría confirmar si esto es un error / inconsistencia antes de archivarlo como tal en el R-forge tracker.

Considere esta data.table :

require(data.table) DT <- data.table(x=c(1,0,NA), y=1:3)

Ahora, para acceder a todas las filas del DT que no son 0, podríamos hacerlo de la siguiente manera:

DT[x != 0] # x y # 1: 1 1 DT[!(x == 0)] # x y # 1: 1 1 # 2: NA 3

Al acceder a DT[x != 0] y DT[!(x==0)] obtienen resultados diferentes cuando la operación lógica subyacente es equivalente.

Nota: Convertir esto en un data.frame y ejecutar estas operaciones dará resultados que son idénticos entre sí para ambas operaciones lógicamente equivalentes, pero ese resultado es diferente de ambos resultados de la tabla de datos. Para una explicación de por qué, mire ?`[` la sección NAs in indexing .

Edición: ya que algunos de ustedes han enfatizado la igualdad con data.frame , aquí está el fragmento de la salida de las mismas operaciones en data.frame:

DF <- as.data.frame(DT) # check ?`[` under the section `NAs in indexing` as to why this happens DF[DF$x != 0, ] # x y # 1 1 1 # NA NA NA DF[!(DF$x == 0), ] # x y # 1 1 1 # NA NA NA

Creo que esto es una inconsistencia y ambos deberían proporcionar el mismo resultado. Pero, ¿qué resultado? La documentación para [.data.table dice:

i ---> Vector entero, lógico o de caracteres, expresión de nombres de columna, lista o tabla de datos.

los vectores enteros y lógicos funcionan de la misma manera que lo hacen en [.data.frame. Aparte de las NA, las lógicas i se tratan como FALSE y una única lógica NA no se recicla para que coincida con el número de filas, como lo está en [.data.frame.

Está claro por qué los resultados son diferentes de lo que se obtendría al hacer la misma operación en un data.frame . Pero aún así, dentro de data.table, si este es el caso, entonces ambos deberían regresar:

# x y # 1: 1 1

[.data.table código fuente de [.data.table y ahora entiendo por qué sucede esto. Consulte esta publicación para obtener una explicación detallada de por qué sucede esto.

Brevemente, x != 0 evalúa como "lógico" y NA se reemplaza a FALSE. Sin embargo !(x==0) , primero (x == 0) se evalúa como lógico y NA se reemplaza a FALSE. Luego ocurre la negación, lo que hace que NA convierta en TRUE .

Entonces, mi primera (o más bien la principal) pregunta es: ¿es esto un error / inconsistencia? Si es así, lo archivaré como uno en data.table R-forge tracker. Si no, me gustaría saber la razón de esta diferencia y me gustaría sugerir una corrección a la documentación que explica esta diferencia (¡a la documentación ya increíble!).

Edición: Siguiendo con los comentarios, la segunda pregunta es si el manejo de data.table para subconjuntos mediante la indexación con columnas que contienen NA asemeja al de data.frame (Pero estoy de acuerdo, siguiendo el comentario de @ Roland de que esto puede conducir a opiniones y estoy perfectamente bien si no contesto esta pregunta en absoluto).


Creo que es un comportamiento documentado y consistente.

Lo más importante a tener en cuenta es que el prefijo ! dentro del argumento i hay un indicador para no unirse, por lo que x != 0 y !(x==0) ya no son la misma operación lógica cuando se trabaja con el manejo documentado de NA dentro de data.table

La sección de noticias sobre el not join

A new "!" prefix on i signals ''not-join'' (a.k.a. ''not-where''), #1384i. DT[-DT["a", which=TRUE, nomatch=0]] # old not-join idiom, still works DT[!"a"] # same result, now preferred. DT[!J(6),...] # !J == not-join DT[!2:3,...] # ! on all types of i DT[colA!=6L | colB!=23L,...] # multiple vector scanning approach (slow) DT[!J(6L,23L)] # same result, faster binary search ''!'' has been used rather than ''-'' : * to match the ''not-join''/''not-where'' nomenclature * with ''-'', DT[-0] would return DT rather than DT[0] and not be backwards compatible. With ''!'', DT[!0] returns DT both before (since !0 is TRUE in base R) and after this new feature. * to leave DT[+J...] and DT[-J...] available for future use

Y a partir de ?data.table

Todos los tipos de ''i'' pueden tener el prefijo!. Esto indica que se debe realizar una no combinación o no selección. En la documentación de data.table, donde nos referimos al tipo de ''i'', nos referimos al tipo de ''i'' después de ''!'', Si está presente. Ver ejemplos

¿Por qué es consistente con el manejo documentado de NA dentro de data.table?

NA valores de NA se consideran FALSOS. Piensa en ello como hacer isTRUE en cada elemento.

por lo tanto, DT[x!=0] se indexa con TRUE FALSE NA que se convierte en TRUE FALSE FALSE debido al manejo documentado de NA.

Usted está queriendo sub-establecer cuando las cosas son VERDADERAS.

Esto significa que está obteniendo aquellos donde x! = 0 es VERDADERO (y no NA)

DT[!(x==0)] usa los estados de no unión que desea que no sean 0 (que pueden incluir los valores de NA ).

consultas de seguimiento / otros ejemplos

DT[!(x!=0)]

## returns x y 1: 0 2 2: NA 3

x!=0 es VERDADERO para un valor, por lo que la no unión devolverá lo que no es verdadero. (es decir, lo que era FALSE (en realidad == 0 ) o NA

DT[!!(x==0)]

## returns x y 1: 0 2 2: NA 3

Esto se analiza como !(!(x==0)) . El prefijo ! denota una no unión, y el interior !(x==0) se analiza de manera idéntica a x!=0 , por lo que se aplica el razonamiento del caso anterior.


Llego un mes tarde a esta discusión, pero con nuevos ojos y leyendo todos los comentarios ... sí, creo que sería mejor que DT[x != .] Incluyera alguna fila con NA en x en el resultado, y Debería cambiarlo para hacer eso.

Nueva respuesta agregada a la pregunta vinculada con más antecedentes desde un ángulo diferente:

https://.com/a/17008872/403310


Mi opinión es que el subset hace lo correcto y tanto data.table como data.frame no lo hacen, data.frame que data.frame el más tonto de todos. Así que en lo que respecta a su pregunta, no, no creo que data.table deba hacer lo mismo que data.frame , debería hacer lo mismo que un subset .

Para el registro, aquí está la salida del subset :

subset(DF, x != 0) # x y #1 1 1 subset(DF, !(x == 0)) # x y #1 1 1 # # or if you want the NA''s as well subset(DF, is.na(x) | x != 0) # x y #1 1 1 #3 NA 3

Quiero desarrollar un poco sobre por data.frame salida de data.frame es tonta. La primera línea en la descripción de [.data.frame dice: "Extraiga o reemplace subconjuntos de marcos de datos" . La salida que devuelve, donde tiene una fila con rowname = NA y todos los elementos iguales a NA son en absoluto "subconjuntos" de la trama de datos dada, haciendo que la salida sea inconsistente con el significado de la función. También es una gran molestia desde el punto de vista del usuario, ya que uno tiene que estar siempre al tanto de estas cosas y encontrar formas de evitar este comportamiento.

En lo que data.table salida de data.table , es claramente inconsistente, pero al menos menos tonta, ya que en ambos casos en realidad devuelve subconjuntos de la tabla de datos original.


A partir de la versión 1.8.11 la ! no activa una no unión para las expresiones lógicas y los resultados para las dos expresiones son los mismos:

DT <- data.table(x=c(1,0,NA), y=1:3) DT[x != 0] # x y #1: 1 1 DT[!(x == 0)] # x y #1: 1 1

Un par de otras expresiones mencionadas en la respuesta de @mnel también se comportan de una manera más predecible ahora:

DT[!(x != 0)] # x y #1: 0 2 DT[!!(x == 0)] # x y #1: 0 2