En el análisis de regresión lineal simple, el objetivo es modelar la relación entre una variable respuesta cuantitativa y y una variable predictora x mediante una línea recta:
y = \beta_0 + \beta_1 x + \epsilon, \quad \epsilon \sim N(0, \sigma^2)
Sin embargo, la presencia de observaciones atípicas (outliers) o puntos con alta influencia puede distorsionar gravemente las estimaciones por Mínimos Cuadrados Ordinarios, alterando la pendiente, el intercepto, el coeficiente de determinación (R^2) e invalidando las pruebas de hipótesis sobre los supuestos del modelo.
ggplot(datos_contaminados, aes(x = x, y = y)) +# Puntos normales en azul, el atípico destacado en rojogeom_point(aes(color = x ==12), size =3) +scale_color_manual(values =c("navy", "red")) +# Recta original (sin el atípico)geom_abline(intercept =coef(modelo_original)[1], slope =coef(modelo_original)[2], color ="blue", linewidth =1.2, linetype ="solid") +# Recta contaminada (con el atípico)geom_abline(intercept =coef(modelo_contaminado)[1], slope =coef(modelo_contaminado)[2], color ="red", linewidth =1.2, linetype ="dashed") +labs(title ="Efecto devastador de un solo valor atípico en OLS",subtitle ="Línea azul: muestra el modelo real.Línea roja: muestra cómo se deforma al incluir el punto rojo",x ="Variable Predictora (x)",y ="Variable Respuesta (y)") +theme_minimal() +theme(legend.position ="none")
summary(modelo_contaminado)
Call:
lm(formula = y ~ x, data = datos_contaminados)
Residuals:
Min 1Q Median 3Q Max
-42.387 -1.776 0.902 4.602 7.866
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 8.5242 3.5254 2.418 0.02212 *
x 1.5719 0.5512 2.852 0.00794 **
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 8.843 on 29 degrees of freedom
Multiple R-squared: 0.219, Adjusted R-squared: 0.1921
F-statistic: 8.131 on 1 and 29 DF, p-value: 0.007936
summary(modelo_original)
Call:
lm(formula = y ~ x, data = datos)
Residuals:
Min 1Q Median 3Q Max
-3.1495 -0.5404 -0.1273 1.0565 2.6500
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 2.93678 0.61179 4.80 4.79e-05 ***
x 2.84464 0.09995 28.46 < 2e-16 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 1.471 on 28 degrees of freedom
Multiple R-squared: 0.9666, Adjusted R-squared: 0.9654
F-statistic: 810 on 1 and 28 DF, p-value: < 2.2e-16
Modelo contaminado
Modelo Original
\hat \beta_0
8.52
2.93
\hat \beta_1
1.57
2.84
R^2
0.219
0.966
Valores atípicos
También llamados observaciones atípicas.
Valores que distan mucho del resto del conjunto observado (Montgomery, Peck y Vining, 2012).
Existen valores atípicos tanto en la variable respuesta (vertical outliers, o simplemente outliers) como en las variables predictoras (leverages) (Rousseeuw y Leroy, 1987).
Tipos de valores atípicos
Un outlier es atípico en la variable respuesta; su residual dista extremadamente de los demás (3 a 4 desviaciones estándar) (Montgomery, Peck y Vining, 2012).
Un good leverage es atípico en alguna de las variables predictoras, distando del clúster y conservando el comportamiento correspondiente en la variable respuesta (Rousseeuw y Leroy, 1987).
Un bad leverage es atípico en alguna de las variables predictoras, distando del clúster, pero sin conservar el comportamiento en la respuesta (Rousseeuw y Leroy, 1987).
Causa de valores atípicos (Kowalskie, 2025)
Errores en la recopilación o entrada de datos (error al momento de ingresar un dato, error de un instrumento).
Acontecimientos extraordinarios o causas no conocidas (una pandemia, una liquidación, un cambio de políticas).
Valores que son genuinamente extremos, pero válidos (calificaciones, riquezas).
Relevancia de los valores atípicos
Datos Factibles:
Pueden controlar muchas propiedades claves del modelo.
Pueden hacer resaltar inadecuaciones en el modelo.
Si el valor atípico es un punto de respuesta especialmente deseable, sería en extremo valioso conocer los valores de los regresores, cuando se observó esa respuesta.
Si la muestra es pequeña, los datos pueden ser legítimos, pero extremos, por lo que valdría la pena conservarlos.
Los análisis de identificación y de seguimiento de los valores atípicos con frecuencia dan como resultado mejoras en el proceso, o nuevos conocimientos acerca de factores cuyo efecto sobre la respuesta se desconocía antes.
Datos “Malos”:
Se deben a eventos desacostumbrados.
Algunos ejemplos son la medición o análisis incorrectos, el registro erróneo de los datos o la falla de un instrumento de medición adecuado.
Si este es el caso, se deberían corregir o eliminar del conjunto de datos.
Detección de valores atípicos
Se detectan valores atípicos visualmente, ya que parecen como puntos individuales que se alejan del patrón general. Para ello se utilizan histogramas, boxplots, scatterplots, centroides y clústers, y elipses de confianza (Bettinger y Spring, 2020).
A continuación, mostraremos cómo detectar, diagnosticar y tratar valores atípicos utilizando R, empleando la base de datos airquality para observar cómo la limpieza de datos ayuda a restaurar el comportamiento adecuado del modelo y la normalidad de los errores.
Preparación y Análisis Exploratorio
Cargamos los datos y ajustamos nuestro modelo inicial de regresión lineal simple tomando como variable respuesta el Ozono (Ozone) y como predictora la Temperatura (Temp).
library(ggplot2)library(MASS)library(nortest)# Cargar y limpiar valores faltantes (NA) en airqualitydata("airquality")air_clean <-na.omit(airquality)# Ajuste del modelo OLS originalmodelo_orig <-lm(Ozone ~ Temp, data = air_clean)summary(modelo_orig)
Call:
lm(formula = Ozone ~ Temp, data = air_clean)
Residuals:
Min 1Q Median 3Q Max
-40.922 -17.459 -0.874 10.444 118.078
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -147.6461 18.7553 -7.872 2.76e-12 ***
Temp 2.4391 0.2393 10.192 < 2e-16 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 23.92 on 109 degrees of freedom
Multiple R-squared: 0.488, Adjusted R-squared: 0.4833
F-statistic: 103.9 on 1 and 109 DF, p-value: < 2.2e-16
Gráficamente podemos observar la relación y ubicar de manera visual el punto atípico superior (una concentración de ozono inusualmente alta para esa temperatura):
ggplot(air_clean, aes(x = Temp, y = Ozone)) +geom_point(color ="navy", size =2) +geom_smooth(method ="lm", color ="red", se =FALSE) +labs(title ="Regresión Lineal: Ozone vs Temp",subtitle ="Modelo OLS con observaciones originales",x ="Temperatura (°F)",y ="Ozono (ppb)") +theme_minimal()
`geom_smooth()` using formula = 'y ~ x'
Detección Numérica de Valores Atípicos e Influencia
Para ir más allá de la simple inspección visual, la literatura estadística define tres herramientas fundamentales de diagnóstico:
Leverage (h_{ii}): Mide cuán extrema es una observación en el espacio de la variable predictora x. Se considera un valor extremo en x si supera el umbral:
Distancia de Cook (D_i): Mide el impacto global que tiene la eliminación de la observación i-ésima sobre todo el conjunto de estimaciones del modelo. El umbral de alerta común es D_i \ge \frac{4}{n - p}.
Residuales Estudentizados (RStudentt_i): Evalúan si el error de predicción es extremadamente grande (3 a 4 desviaciones estándar), detectando outliers en la variable respuesta y. Se suele usar la región de rechazo |t_i| > 3.
Vamos a calcular e identificar estos puntos en nuestro código de R:
n <-nrow(air_clean)p <-2# Intercepto y pendiente# 1. Leveragehat_vals <-hatvalues(modelo_orig)umbral_hat <-3* (p / n)# 2. Distancia de Cookcook_vals <-cooks.distance(modelo_orig)umbral_cook <-4/ (n - p)# 3. RStudentr_student <-rstudent(modelo_orig)# Identificar filas problemáticasatipicos_rstudent <-which(abs(r_student) >3)atipicos_cook <-which(cook_vals > umbral_cook)cat("Observaciones con RStudent > 3:", atipicos_rstudent, "\n")
Observaciones con RStudent > 3: 23 34 77
cat("Observaciones con Distancia de Cook alta:", atipicos_cook, "\n")
Observaciones con Distancia de Cook alta: 23 34 63 77 80
Visualicemos las Distancias de Cook para identificar claramente el impacto de la observación clave (la número 77):
plot(modelo_orig, which =4, col ="blue", pch =16)abline(h = umbral_cook, col ="red", lty =2)
Tratamiento de Valores Atípicos
Ante la presencia de valores atípicos confirmados como problemáticos o erróneos, existen dos vías principales: la eliminación (dropping) o la imputación / winsorización.
Opción A: Eliminación de observaciones extremas
Si determinamos que el punto responde a un error de medición o un evento extraordinario ajeno al fenómeno de estudio, podemos eliminarlo y reajustar el modelo:
# Identificamos y filtramos la observación 77 (la de mayor RStudent/Cook)air_filtered <- air_clean[-atipicos_rstudent, ]# Reajustar modelo sin el outliermodelo_filtrado <-lm(Ozone ~ Temp, data = air_filtered)summary(modelo_filtrado)
Call:
lm(formula = Ozone ~ Temp, data = air_filtered)
Residuals:
Min 1Q Median 3Q Max
-38.137 -14.772 1.216 12.180 56.132
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -142.5091 14.6182 -9.749 <2e-16 ***
Temp 2.3413 0.1867 12.538 <2e-16 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 18.62 on 106 degrees of freedom
Multiple R-squared: 0.5973, Adjusted R-squared: 0.5935
F-statistic: 157.2 on 1 and 106 DF, p-value: < 2.2e-16
lillie.test(modelo_orig$residuals)
Lilliefors (Kolmogorov-Smirnov) normality test
data: modelo_orig$residuals
D = 0.094492, p-value = 0.01631
lillie.test(modelo_filtrado$residuals)
Lilliefors (Kolmogorov-Smirnov) normality test
data: modelo_filtrado$residuals
D = 0.074334, p-value = 0.1509
Opción B: Winsorización (Alternativa para conservar datos)
Si los valores son extremos pero legítimos (es decir, pertenecen a la población pero alargan las colas de la distribución), la Winsorización sustituye los valores que rebasan los percentiles extremos por dichos umbrales, reduciendo su peso sin perder el tamaño de la muestra.
A diferencia de la eliminación (dropping), que borra por completo la observación extrema, la Winsorización consiste en sustituir los valores más extremos (tanto los más altos como los más bajos) por el valor del percentil correspondiente fijado como límite (por ejemplo, el percentil 95 para los valores altos y el percentil 5 para los bajos).
¿Cuándo se debe utilizar?
Valores reales pero extremos: Se recomienda cuando verificas que el dato es legítimo y pertenece a la población de estudio (por ejemplo, salarios muy altos o temperaturas sumamente inusuales), pero su magnitud es tal que deforma los estimadores de Mínimos Ordinarios Cuadrados (OLS).
Preservar el tamaño de muestra: Es ideal cuando tienes muestras pequeñas donde cada observación cuenta y eliminar filas reduciría drásticamente los grados de libertad del modelo.
Colas largas naturales: Cuando la distribución de la variable presenta de manera natural colas pesadas.
Nota importante: Si el valor atípico es claramente un error de captura o de medición, la Winsorización no es la solución adecuada, ya que mantendrías un dato falso aunque con el valor del percentil; en esos casos se prefiere corregir o eliminar)
# 1. Definir los límites de los percentiles (por ejemplo, 5% inferior y 5% superior)q_inf <-quantile(air_clean$Ozone, 0.05, na.rm =TRUE)q_sup <-quantile(air_clean$Ozone, 0.95, na.rm =TRUE)# 2. Crear una nueva columna en el dataframe con la variable Ozone winsorizadaair_clean$Ozone_winsorized <-pmin(pmax(air_clean$Ozone, q_inf), q_sup)# 3. Ajustar el nuevo modelo con la variable winsorizadamodelo_winsor <-lm(Ozone_winsorized ~ Temp, data = air_clean)# Comparar los coeficientes del modelo original vs el winsorizadosummary(modelo_orig)
Call:
lm(formula = Ozone ~ Temp, data = air_clean)
Residuals:
Min 1Q Median 3Q Max
-40.922 -17.459 -0.874 10.444 118.078
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -147.6461 18.7553 -7.872 2.76e-12 ***
Temp 2.4391 0.2393 10.192 < 2e-16 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 23.92 on 109 degrees of freedom
Multiple R-squared: 0.488, Adjusted R-squared: 0.4833
F-statistic: 103.9 on 1 and 109 DF, p-value: < 2.2e-16
summary(modelo_winsor)
Call:
lm(formula = Ozone_winsorized ~ Temp, data = air_clean)
Residuals:
Min 1Q Median 3Q Max
-39.752 -16.327 0.085 11.738 64.936
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -141.1259 16.0769 -8.778 2.58e-14 ***
Temp 2.3442 0.2051 11.427 < 2e-16 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 20.5 on 109 degrees of freedom
Multiple R-squared: 0.545, Adjusted R-squared: 0.5409
F-statistic: 130.6 on 1 and 109 DF, p-value: < 2.2e-16
Visualización gráfica del efecto
# Gráfico comparativoplot(air_clean$Temp, air_clean$Ozone, pch =16, col ="gray70",main ="Efecto de la Winsorización en Regresión Lineal",xlab ="Temperatura (°F)", ylab ="Ozono (ppb)")# Puntos originales que fueron "recortados" (winsorizados)points(air_clean$Temp[air_clean$Ozone > q_sup], air_clean$Ozone[air_clean$Ozone > q_sup], col ="purple", pch =17, cex =1.3)# Rectas de regresiónabline(modelo_orig, col ="red", lwd =2) # OLS Original (afectado por el pico)abline(modelo_winsor, col ="forestgreen", lwd =2, lty =2) # OLS Winsorizadolegend("topleft", legend =c("OLS Original", "OLS Winsorizado", "Valores acotados"),col =c("red", "forestgreen", "purple"), lty =c(1, 2, NA), pch =c(NA, NA, 17), lwd =2)
# Obtener los residuos estandarizados o estudentizados del modeloresiduos_std <-rstandard(modelo_orig)# Crear un data frame para ggplotdf_qq <-data.frame(residuos = residuos_std)# Generar el Q-Q plot con ggplot2ggplot(df_qq, aes(sample = residuos)) +stat_qq(color ="navy", size =2) +stat_qq_line(color ="red", linetype ="dashed", linewidth =1) +labs(title ="Gráfico Q-Q de Residuos Estándar",subtitle ="Verificación del supuesto de normalidad para modelo_orig",x ="Cuantiles Teóricos",y ="Cuantiles Muestrales (Residuos)" ) +theme_minimal()
# Obtener los residuos estandarizados o estudentizados del modeloresiduos_stdwin <-rstandard(modelo_winsor)# Crear un data frame para ggplotdf_qqwin <-data.frame(residuos = residuos_stdwin)# Generar el Q-Q plot con ggplot2ggplot(df_qqwin, aes(sample = residuos)) +stat_qq(color ="navy", size =2) +stat_qq_line(color ="red", linetype ="dashed", linewidth =1) +labs(title ="Gráfico Q-Q de Residuos Estándar",subtitle ="Verificación del supuesto de normalidad para modelo_winsor",x ="Cuantiles Teóricos",y ="Cuantiles Muestrales (Residuos)" ) +theme_minimal()
lillie.test(modelo_orig$residuals)
Lilliefors (Kolmogorov-Smirnov) normality test
data: modelo_orig$residuals
D = 0.094492, p-value = 0.01631
lillie.test(modelo_winsor$residuals)
Lilliefors (Kolmogorov-Smirnov) normality test
data: modelo_winsor$residuals
D = 0.070994, p-value = 0.1845