NA significa "desconocido" - y se propaga
Los conjuntos de datos reales tienen agujeros: la pregunta de la encuesta que quedó en blanco, el sensor que perdió una lectura. R representa cada agujero con NA - not available. El modelo mental crucial: NA no es cero, ni una cadena vacía, ni un número especial. Significa "aquí hay un valor, pero no sabemos cuál es".
Tómatelo en serio y el comportamiento de R se vuelve lógico. ¿Cuánto es un número desconocido más uno? Desconocido. ¿Cuál es la media de 4, 8 y algo desconocido? Desconocida - el valor que falta podría ser cualquiera, así que la media podría ser cualquiera:
Las tres imprimen NA. Este contagio es una característica, no un fallo: R se niega a fingir discretamente que conoce una respuesta que no conoce. Una hoja de cálculo que se salta las celdas en blanco en silencio puede ocultar que falta media columna; R te obliga a darte cuenta y a decidir qué deben significar los valores ausentes para tu análisis. El resto de este artículo trata de tomar esa decisión deliberadamente.
Comprobar NA: is.na(), nunca ==
Aquí está la primera trampa en la que cae todo el mundo. Quieres encontrar los valores ausentes, así que escribes una comparación - y no funciona:
x == NA devuelve NA NA NA - ni un solo TRUE. ¿Por qué? Sigue la lógica de "desconocido": ¿es 4 igual a algún valor desconocido? No se puede decir - el desconocido podría ser 4. Incluso el hueco NA se compara como NA: ¿es un desconocido igual a otro? Desconocido. La comparación con NA nunca puede devolver TRUE o FALSE, así que como comprobación es inútil - y peor aún, una máscara toda de NA dentro de [ ] no selecciona lo que esperas.
La herramienta correcta es is.na(), construida para responder exactamente a esta pregunta y que devuelve lógicos honestos: FALSE TRUE FALSE. A partir de ahí, dos modismos que usarás constantemente:
sum(is.na(x)) cuenta los valores ausentes (TRUE suma 1) - ejecútalo sobre cada columna de un conjunto de datos nuevo antes que nada. which(is.na(x)) los localiza. Y x[!is.na(x)] conserva solo los valores observados - eliminación manual mediante una máscara lógica, el mismo patrón de filtrado de vectores de siempre.
Saltarse los NA en los resúmenes: na.rm = TRUE
Normalmente no necesitas eliminar los NA a mano, porque las funciones de resumen de R llevan una salida de emergencia incorporada - el argumento na.rm (NA remove):
Con na.rm = TRUE, la función descarta los valores ausentes y calcula con lo que queda: la media de 4 y 8 es 6. sum(), sd(), median(), min(), max(), var() - toda la familia de la estadística descriptiva lo acepta.
Fíjate en que el valor por defecto es FALSE. Eso es R siendo tozudo a tu favor: quiere que ignorar los datos ausentes sea una elección explícita que dejes por escrito, no un valor por defecto silencioso. Cuando escribes na.rm = TRUE, estás afirmando "aquí los valores ausentes se pueden ignorar sin peligro" - lo que es cierto cuando un sensor perdió unas cuantas lecturas al azar, y peligrosamente falso cuando, pongamos, quienes menos ganan se saltaron la pregunta sobre ingresos. El argumento te hace responsable de esa decisión.
Eliminar filas incompletas: na.omit() y complete.cases()
En un data frame, la ausencia vive en las celdas, pero el análisis suele trabajar fila a fila - así que la operación habitual es eliminar las filas que tengan algún NA:
na.omit(df) devuelve el data frame menos toda fila que contenga al menos un NA - aquí solo sobrevive Rosa. complete.cases(df) devuelve la máscara lógica de filas (TRUE FALSE FALSE) detrás de la misma idea, e indexar con ella da resultados idénticos con dos ventajas: puedes contar primero lo que estás a punto de perder (sum(!complete.cases(df))) y puedes restringir qué columnas importan - df[complete.cases(df[, "age"]), ] elimina solo las filas sin age, conservando a Mia aunque su puntuación sea desconocida.
Esa forma restringida por columnas importa más de lo que parece: na.omit() sobre un data frame ancho puede descartar en silencio la mayoría de tus filas por culpa de NA en columnas que nunca pensabas analizar. Sabe cuántas filas estás eliminando, y por qué, antes de eliminarlas.
Sustituir NA
A veces lo correcto es rellenar los agujeros en lugar de borrar filas. El modismo combina is.na() con una asignación:
Léelo como: "en los huecos donde visits falta, pon 0". Esto es legítimo exactamente cuando NA codifica un valor conocido - un cliente sin registro de visitas tuvo genuinamente cero visitas.
Pero sé honesto sobre cuándo eso es cierto. Si NA significa "no conseguimos medirlo", sustituirlo por 0 fabrica datos: reemplazar las notas de examen ausentes por 0 arrastra la media hacia abajo como si esos estudiantes hubieran sacado un cero, cuando en realidad no sabes qué sacaron. Compara la media de arriba (2,4) con la media con na.rm del original (4): los mismos datos, afirmaciones distintas. Sustituir por la media o la mediana distorsiona menos, pero sigue infravalorando la variabilidad. La regla: imputa un valor solo cuando puedas decir, con palabras llanas, por qué ese valor es lo que la entrada ausente realmente era. Si no, conserva el NA y usa na.rm - "desconocido" es a menudo el valor más veraz del conjunto de datos.
NA frente a NULL frente a NaN frente a Inf
R tiene cuatro valores especiales parecidos que significan cosas genuinamente distintas:
| Valor | Significado | Longitud | Origen típico |
|---|---|---|---|
NA | Existe un valor pero es desconocido | 1 (ocupa un hueco) | Datos ausentes |
NULL | Ningún objeto en absoluto | 0 (sin hueco) | Elemento de lista borrado, resultado vacío |
NaN | Cálculo con respuesta indefinida | 1 | 0 / 0, log(-1) |
Inf | Un número más allá de lo representable | 1 | 1 / 0, desbordamiento |
Las distinciones que importan en la práctica: NULL desaparece dentro de los vectores (c(1, NULL, 3) tiene dos elementos - no puede representar una observación ausente), mientras que NA mantiene su sitio. NaN cuenta como ausente (is.na(NaN) es TRUE, así que na.rm también lo elimina), pero lo contrario es falso - is.nan(NA) es FALSE. Y Inf no es ausente - es un número real y comparable (Inf > 1e300 es TRUE), así que na.rm no lo eliminará; usa is.finite() para filtrar y quedarte con los números corrientes.
Para completar: NA viene discretamente en variantes tipadas (NA_integer_, NA_real_, NA_character_) para poder alojarse en cualquier vector sin romper la regla de un solo tipo. Rara vez las escribirás, pero las verás en el código de los paquetes y en los mensajes de error de dplyr.
Lo que te llevas
NAsignifica "desconocido", y los desconocidos son contagiosos: cualquier cálculo que toque un NA devuelve NA - por diseño.- Comprueba con
is.na(), nunca con== NA; cuenta los agujeros consum(is.na(x)). na.rm = TRUEhace que las funciones de resumen se salten los NA - una decisión explícita, llamada a llamada, de que los valores ausentes son ignorables.na.omit()elimina las filas incompletas de golpe;complete.cases()te da la máscara, contable y restringible a las columnas que importan.- Sustituye NA (
x[is.na(x)] <- valor) solo cuando puedas justificar qué era realmente el valor ausente. - NA ≠ NULL ≠ NaN ≠ Inf: valor ausente, objeto inexistente, cálculo indefinido, número sin límite.
Lo siguiente: las funciones - empaquetar tu lógica en piezas reutilizables y con nombre.
Preguntas frecuentes
¿Por qué mean() devuelve NA en R?
Porque al menos un valor del vector es NA, y NA es contagioso: si alguna entrada es desconocida, R dice que la respuesta también lo es. Pasa na.rm = TRUE - mean(x, na.rm = TRUE) - para calcular la media de los valores presentes. La mayoría de las funciones de resumen (sum, sd, median, min, max) aceptan el mismo argumento.
¿Cómo se comprueba si hay NA en R?
Con is.na(x), que devuelve TRUE allí donde falta un valor. Nunca compruebes con x == NA - comparar cualquier cosa con un desconocido da NA, no TRUE ni FALSE, así que la comprobación falla en silencio. sum(is.na(x)) cuenta los valores ausentes; which(is.na(x)) encuentra sus posiciones.
¿Cómo se eliminan las filas con NA de un data frame en R?
na.omit(df) elimina toda fila que contenga al menos un NA. Para más control, complete.cases(df) devuelve un vector lógico que marca las filas completamente observadas, así que df[complete.cases(df), ] hace lo mismo de forma explícita - y puedes aplicarlo solo a las columnas que importan, por ejemplo df[complete.cases(df[, c("age", "score")]), ].
¿Cuál es la diferencia entre NA y NULL en R?
NA es un valor ausente - ocupa un hueco en un vector y tiene longitud 1. NULL es la ausencia de un objeto - tiene longitud 0 y desaparece al meterlo en un vector: c(1, NULL, 3) solo tiene dos elementos. Usa NA para un dato ausente; NULL aparece al eliminar elementos de una lista o como un retorno vacío.