r na

Comportamiento inesperado de la tabla de funciones con valores de "NaN"



(2)

Recientemente, me enfrenté a un comportamiento en la función de table que no era el esperado:

Por ejemplo, tomemos el siguiente vector:

ex_vec <- c("Non", "Non", "Nan", "Oui", "NaN", NA)

Si NA valores de NA en mi vector, "NaN" no se considera uno (como se esperaba):

is.na(ex_vec) # [1] FALSE FALSE FALSE FALSE FALSE TRUE

Pero si trato de obtener las diferentes frecuencias de valores:

table(ex_vec) #ex_vec #Nan Non Oui # 1 2 1

"NaN" no aparece en la tabla.

Sin embargo, si "pido" la table para mostrar los valores de NA , obtengo esto:

table(ex_vec, useNA="ifany") #ex_vec # Nan NaN Non Oui <NA> # 1 1 2 1 1

Por lo tanto, las cadenas de caracteres "NaN" se tratan como un valor de NA dentro de la llamada de la table , mientras que se tratan en la salida como un valor no NA .

Lo sé (sería mejor y) podría resolver mi problema convirtiendo mi vector en un factor pero, sin embargo, realmente me gustaría saber qué está pasando aquí. ¿Alguien tiene alguna idea?


Cuando el factor coincide con los niveles de un vector, convierte su lista de exclude al mismo tipo que el vector de entrada:

exclude <- as.vector(exclude, typeof(x))

así que si tu lista de exclusión tiene NaN y tu vector es un carácter, esto sucede:

as.vector(exclude, typeof(letters)) [1] NA "NaN"

Oh querido. Ahora las verdaderas cadenas "NaN" serán excluidas.

Para solucionarlo, use exclude=NA en la table (y factor si está haciendo factores que podrían afectar esto).

Me encanta esto en los documentos por factor :

There are some anomalies associated with factors that have ‘NA’ as a level. It is suggested to use them sparingly, e.g., only for tabulation purposes.

Tranquilizando ...


La primera idea que me vino a la mente fue echar un vistazo a la definición de la table que comienza por:

> table function (..., exclude = if (useNA == "no") c(NA, NaN), useNA = c("no", "ifany", "always"), dnn = list.names(...), deparse.level = 1) {

Suena lógico, por defecto la tabla excluye NA y NaN .

Al excavar dentro del código de la tabla, vemos que si x no es un factor, lo obliga a un factor (no hay nada nuevo aquí, se dice en el documento).

else { a <- factor(a, exclude = exclude)

No encontré nada más que pudiera haber afectado la entrada para forzar a "NaN" en los valores de NA .

Por lo tanto, buscar en el factor para obtener el por qué encontramos la causa raíz:

> factor function (x = character(), levels, labels = levels, exclude = NA, ordered = is.ordered(x), nmax = NA) { [...] # Snipped for brievety exclude <- as.vector(exclude, typeof(x)) x <- as.character(x) levels <- levels[is.na(match(levels, exclude))] # defined in the snipped part above, is the sorted unique values of input vector, coerced to char. f <- match(x, levels) [...] f }

Aquí lo tenemos, el parámetro de exclusión, incluso siendo valores de NA , se convierte en un vector de caracteres.

Entonces lo que pasa es:

> ex_vec <- c("Non", "Non", "Nan", "Oui", "NaN", NA) > excludes<-c(NA,NaN) > as.vector(excludes,"character") [1] NA "NaN" > match(ex_vec,as.vector(excludes,"character")) [1] NA NA NA NA 2 1

Hacemos coincidir el carácter "NaN" como el vector de exclusión que se ha coaccionado al carácter antes de la comparación.