Cómo reemplazar valores faltantes (NA) en R: na.omit y na.rm
⚡ Resumen inteligente
El tutorial "Reemplazar valores faltantes en R" explica cómo detectar valores NA, eliminar filas incompletas con `na.omit()` e imputarlas con la media o la mediana mediante `mutate()`. Este tutorial utiliza el conjunto de datos del Titanic, donde tanto la edad como la tarifa presentan datos faltantes.

¿Qué son los valores faltantes en R?
Los valores faltantes aparecen cuando una observación no tiene un valor registrado en una columna, o cuando un marcador de posición no numérico ocupa el lugar de un número. Deben eliminarse o reemplazarse antes de cualquier cálculo, ya que la mayoría de las funciones de R devuelven NA en cuanto aparece uno.
Este tutorial muestra cómo manejar valores faltantes con la biblioteca dplyr, que forma parte del ecosistema tidyverse para el análisis de datos.
El primer paso siempre es averiguar cuántos valores faltan y dónde.
Cómo detectar y contar valores faltantes en R
Antes de decidir qué hacer con los valores faltantes, es necesario saber cuántos hay y dónde se encuentran. R ofrece cuatro comprobaciones, desde una simple respuesta de sí o no hasta un recuento completo por columna.
# 1. Is there any NA at all? anyNA(df_titanic) # 2. How many in total? sum(is.na(df_titanic)) # 3. How many per column, the most useful view colSums(is.na(df_titanic)) # 4. Percentage missing per column round(colMeans(is.na(df_titanic)) * 100, 1)
En la práctica, la función colSums() es la más recomendable. Devuelve un vector con nombre que muestra un valor por columna, lo que indica inmediatamente si a una variable le faltan algunos valores o si está prácticamente vacía.
Contando filas completas. complete.cases() devuelve TRUE para las filas sin ningún valor faltante, lo que le indica de antemano cuántos datos descartaría na.omit():
sum(complete.cases(df_titanic)) # rows that would survive sum(!complete.cases(df_titanic)) # rows that would be dropped
Una advertencia sobre los marcadores de posición. R solo reconoce NA. Los conjuntos de datos suelen codificar los valores faltantes como una cadena vacía, un espacio, “N/A”, “-” o un número centinela como -99 o 999. Estos pasan desapercibidos en todas las comprobaciones anteriores. Conviértalos al importarlos para que el resto del flujo de trabajo funcione correctamente:
df <- read.csv(PATH, na.strings = c("", " ", "NA", "N/A", "-", "-99"))
Siempre revise el rango de cada columna numérica después de la importación. Una edad de -99 o una tarifa de 9999 son mucho más peligrosas que un valor NA honesto, porque ninguna función le avisará al respecto.
Tipos de datos faltantes: MCAR, MAR y MNAR
El motivo por el que falta un valor determina si es seguro imputarlo. Los estadísticos reconocen tres mecanismos.
- MCAR, desaparecido completamente al azar. La probabilidad de que falte no está relacionada con nada, observado o no, por ejemplo, un sensor que falla en momentos aleatorios.ping o bien, la imputación de estas filas no introduce ningún sesgo, solo una pérdida de precisión.
- MAR, falta al azar. La probabilidad depende de otras variables observadas, pero no del valor faltante en sí. Si los pasajeros de mayor edad tenían menos probabilidades de que se registrara su edad, esta es MAR dadas las demás columnas. La imputación que utiliza esas columnas maneja bien este problema.
- MNAR, falta no aleatoriamente. La probabilidad depende del valor no observado en sí, por ejemplo, que las personas con altos ingresos se nieguen a declarar sus ingresos. Ningún método de imputación puede solucionar esto basándose únicamente en los datos, y la falta de datos en sí misma contiene información valiosa que se puede registrar en una columna de indicadores.
La imputación por la media, tal como se utiliza en este tutorial, solo es válida bajo MCAR y MAR simple. Incluso en esos casos, tiene un coste conocido: rellenar cada hueco con el mismo número reduce la varianza de la columna y debilita su correlación con las demás. Para trabajos serios, utilice un método basado en modelos, como el paquete mice, y mantenga siempre una columna indicadora que señale qué valores se imputaron.
mudar()
mutate() es el dplyr verbo que crea una nueva variable o sobrescribe una existente, lo que lo convierte en la herramienta natural para crear una copia limpia de una columna.
Procederemos en dos partes. Aprenderemos a:
- excluir valores faltantes de un marco de datos
- imputar los valores faltantes con la media y la mediana
El verbo mutate() es muy fácil de usar. Podemos crear una nueva variable siguiendo esta sintaxis:
mutate(df, name_variable_1 = condition, ...) arguments: -df: Data frame used to create a new variable -name_variable_1: Name and the formula to create the new variable -...: No limit constraint. Possibility to create more than one variable inside mutate()
Excluir valores faltantes (NA)
`na.omit()` es una función base de R, no un verbo de dplyr, pero funciona perfectamente con tuberías. Elimina todas las filas que contienen al menos un valor NA. Esta es la opción más rápida, pero rara vez la mejor, ya que un solo valor faltante descarta toda la observación.
Para abordar el problema de las observaciones faltantes, utilizaremos el conjunto de datos del Titanic. En este conjunto de datos, tenemos acceso a la información de los pasajeros a bordo durante la tragedia. Este conjunto de datos tiene muchas NA que deben tenerse en cuenta.
Cargue el archivo CSV desde Internet y luego enumere las columnas que contienen NA:
PATH <- "https://raw.githubusercontent.com/guru99-edu/R-Programming/master/test.csv" df_titanic <- read.csv(PATH, sep = ",") # Return the column names containing missing observations list_na <- colnames(df_titanic)[ apply(df_titanic, 2, anyNA) ] list_na
Salida:
## [1] "age" "fare"
Aquí,
colnames(df_titanic)[apply(df_titanic, 2, anyNA)]
Devuelve los nombres de las columnas que contienen al menos un valor faltante.
A las columnas edad y tarifa les faltan valores.
Podemos eliminarlos con na.omit().
library(dplyr) # Exclude the missing observations df_titanic_drop <-df_titanic %>% na.omit() dim(df_titanic_drop)
Salida:
## [1] 1045 13
El nuevo conjunto de datos contiene 1045 filas en comparación con las 1309 del conjunto de datos original.
Imputar los datos faltantes con la media y la mediana.
También se pueden imputar, es decir, rellenar, los valores faltantes con la media o la mediana. Una buena práctica es crear dos variables separadas para la media y la mediana. Una vez creadas, podemos reemplazar los valores faltantes con las nuevas variables.
Usaremos el método de aplicación para calcular la media de la columna con NA. Veamos un ejemplo
Paso 1) Anteriormente en el tutorial, almacenamos el nombre de las columnas con los valores faltantes en la lista llamada list_na. Usaremos esta lista
Paso 2) Calcula la media con el argumento na.rm = TRUE. Este argumento es obligatorio porque las columnas tienen datos faltantes, y esto le indica a R que los ignore.
# Create mean average_missing <- apply(df_titanic[,colnames(df_titanic) %in% list_na], 2, mean, na.rm = TRUE) average_missing
Code Explicación:
Pasamos 4 argumentos en el método de aplicación.
- df: df_titanic[,colnames(df_titanic) %in% list_na]. Este código devolverá el nombre de las columnas del objeto list_na (es decir, "edad" y "tarifa")
- 2: Calcular la función en las columnas.
- media: Calcular la media
- na.rm = VERDADERO: ignorar los valores faltantes
Salida:
## age fare ## 29.88113 33.29548
Creamos con éxito la media de las columnas que contienen observaciones faltantes. Estos dos valores se utilizarán para reemplazar las observaciones faltantes.
Paso 3) Reemplazar los valores de NA
El verbo mutar de la biblioteca dplyr es útil para crear una nueva variable. No necesariamente queremos cambiar la columna original para poder crear una nueva variable sin NA. mutate es fácil de usar, simplemente elegimos un nombre de variable y definimos cómo crear esta variable. Aquí está el código completo.
# Create a new variable with the mean and median df_titanic_replace <- df_titanic %>% mutate(replace_mean_age = ifelse(is.na(age), average_missing[1], age), replace_mean_fare = ifelse(is.na(fare), average_missing[2], fare))
Code Explicación:
Creamos dos variables, replace_mean_age y replace_mean_fare de la siguiente manera:
- reemplazar_edad_media = ifelse(is.na(edad), falta_promedio[1], edad)
- reemplazar_tarifa_media = ifelse(is.na(tarifa), promedio_faltante[2],tarifa)
Si a la columna edad le faltan valores, reemplácela con el primer elemento de Average_missing (media de edad); de lo contrario, mantenga los valores originales. Misma lógica para la tarifa.
sum(is.na(df_titanic_replace$age))
Salida:
## [1] 263
Tras la sustitución, la nueva columna no contiene ningún valor faltante:
sum(is.na(df_titanic_replace$replace_mean_age))
Salida:
## [1] 0
La columna de edad original contiene 263 valores faltantes, mientras que la nueva columna replace_mean_age los ha rellenado todos con la edad media.
Paso 4) También podemos reemplazar las observaciones faltantes con la mediana.
median_missing <- apply(df_titanic[,colnames(df_titanic) %in% list_na], 2, median, na.rm = TRUE) df_titanic_replace <- df_titanic %>% mutate(replace_median_age = ifelse(is.na(age), median_missing[1], age), replace_median_fare = ifelse(is.na(fare), median_missing[2], fare)) head(df_titanic_replace)
Salida:
Paso 5) En conjuntos de datos extensos, el método paso a paso se vuelve tedioso. La función sapply() simplifica todo el procedimiento a una sola instrucción, aunque a costa de no visualizar nunca los valores imputados.
sapply no crea un marco de datos, por lo que podemos envolver la función sapply() dentro de data.frame() para crear un objeto de marco de datos.
# Quick code to replace missing values with the mean df_titanic_impute_mean <- data.frame( sapply( df_titanic, function(x) ifelse(is.na(x), mean(x, na.rm = TRUE), x)))
Imputación moderna con replace_na() y across()
Los métodos apply() y sapply() descritos anteriormente siguen funcionando, pero tidyr y dplyr ahora expresan las mismas operaciones de forma más segura y legible.
replace_na() para valores fijos. tidyr::replace_na() toma una lista con nombre de columnas y sus reemplazos:
library(tidyr) df_titanic %>% replace_na(list(age = 29.88, fare = 33.30))
a través() para cada columna numérica. Este es el reemplazo directo y seguro de tipos para la línea de código sapply(), y a diferencia de sapply(), nunca toca columnas de caracteres o factores:
library(dplyr) # Mean-impute every numeric column df_titanic %>% mutate(across(where(is.numeric), ~ ifelse(is.na(.x), mean(.x, na.rm = TRUE), .x))) # Median-impute instead df_titanic %>% mutate(across(where(is.numeric), ~ ifelse(is.na(.x), median(.x, na.rm = TRUE), .x)))
⚠️ Por qué el atajo sapply() es arriesgado: El ejemplo de una sola línea sapply() se ejecuta todas columna, incluyendo caracteres y factores. Llamar a mean() en esas columnas devuelve NA con una advertencia, y sapply() convierte todo el resultado a caracteres. La versión across(where(is.numeric), …) anterior evita esto por completo.
coalesce() para columnas de reserva. Cuando una segunda columna puede proporcionar el valor faltante, coalesce() devuelve la primera entrada no faltante entre sus argumentos:
df %>% mutate(age_final = coalesce(age, age_estimated, 0))
Lleva un registro de los cambios que hayas realizado. Agregue una bandera antes de la imputación, para que cualquier modelo posterior pueda aprender del hecho de que faltaba un valor:
df_titanic %>%
mutate(age_was_missing = is.na(age),
age = ifelse(is.na(age), mean(age, na.rm = TRUE), age))
Manejo de valores faltantes en R: Referencia del método
En este tutorial se abordan tres enfoques:
- Excluir todas las observaciones faltantes.
- Imputar con la media
- Imputar con la mediana
La siguiente tabla resume la detección y eliminación:
| Biblioteca | Objetivo | Code |
|---|---|---|
| bases | Listar observaciones faltantes |
colnames(df)[apply(df, 2, anyNA)] |
| bases | Eliminar todas las filas que contengan NA |
na.omit(df) |
La imputación de media o mediana se puede realizar de dos formas.
- Usando aplicar
- usando sapply
| Método | Detalles | Ventajas | Desventajas |
|---|---|---|---|
| Paso a paso con aplicar | Verifique las columnas que faltan, calcule la media/mediana, almacene el valor, reemplace con mutate() | Puedes ver la media o mediana imputada. | Más tiempo de ejecución. Puede ser lento con un gran conjunto de datos |
| Manera rápida con sapply | Utilice sapply() y data.frame() para buscar y reemplazar automáticamente los valores faltantes con media/mediana | Código corto y rápido. | Los valores imputados nunca se muestran. |



