Los análisis de normalidad, también llamados contrastes de normalidad, tienen como objetivo analizar cuánto difiere la distribución de los datos observados respecto a lo esperado si procediesen de una distribución normal con la misma media y desviación típica. Pueden diferenciarse tres estrategias: las basadas en representaciones gráficas, en métodos analíticos y en test de hipótesis.
library(ggplot2)
## Warning: package 'ggplot2' was built under R version 4.2.3
ggplot(data=mtcars, aes(x=mpg)) +
geom_histogram(aes(y=..density.., fill=..count..)) +
scale_fill_gradient(low = "red", high = "black") +
stat_function(fun=dnorm, colour = "blue", args = list(mean(mtcars$mpg),
sd=sd(mtcars$mpg))) +
ggtitle("Histograma con curva normal teórica")
## Warning: The dot-dot notation (`..density..`) was deprecated in ggplot2 3.4.0.
## ℹ Please use `after_stat(density)` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
mtcars
## mpg cyl disp hp drat wt qsec vs am gear carb
## Mazda RX4 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4
## Mazda RX4 Wag 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4
## Datsun 710 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1
## Hornet 4 Drive 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1
## Hornet Sportabout 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2
## Valiant 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1
## Duster 360 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4
## Merc 240D 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2
## Merc 230 22.8 4 140.8 95 3.92 3.150 22.90 1 0 4 2
## Merc 280 19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4
## Merc 280C 17.8 6 167.6 123 3.92 3.440 18.90 1 0 4 4
## Merc 450SE 16.4 8 275.8 180 3.07 4.070 17.40 0 0 3 3
## Merc 450SL 17.3 8 275.8 180 3.07 3.730 17.60 0 0 3 3
## Merc 450SLC 15.2 8 275.8 180 3.07 3.780 18.00 0 0 3 3
## Cadillac Fleetwood 10.4 8 472.0 205 2.93 5.250 17.98 0 0 3 4
## Lincoln Continental 10.4 8 460.0 215 3.00 5.424 17.82 0 0 3 4
## Chrysler Imperial 14.7 8 440.0 230 3.23 5.345 17.42 0 0 3 4
## Fiat 128 32.4 4 78.7 66 4.08 2.200 19.47 1 1 4 1
## Honda Civic 30.4 4 75.7 52 4.93 1.615 18.52 1 1 4 2
## Toyota Corolla 33.9 4 71.1 65 4.22 1.835 19.90 1 1 4 1
## Toyota Corona 21.5 4 120.1 97 3.70 2.465 20.01 1 0 3 1
## Dodge Challenger 15.5 8 318.0 150 2.76 3.520 16.87 0 0 3 2
## AMC Javelin 15.2 8 304.0 150 3.15 3.435 17.30 0 0 3 2
## Camaro Z28 13.3 8 350.0 245 3.73 3.840 15.41 0 0 3 4
## Pontiac Firebird 19.2 8 400.0 175 3.08 3.845 17.05 0 0 3 2
## Fiat X1-9 27.3 4 79.0 66 4.08 1.935 18.90 1 1 4 1
## Porsche 914-2 26.0 4 120.3 91 4.43 2.140 16.70 0 1 5 2
## Lotus Europa 30.4 4 95.1 113 3.77 1.513 16.90 1 1 5 2
## Ford Pantera L 15.8 8 351.0 264 4.22 3.170 14.50 0 1 5 4
## Ferrari Dino 19.7 6 145.0 175 3.62 2.770 15.50 0 1 5 6
## Maserati Bora 15.0 8 301.0 335 3.54 3.570 14.60 0 1 5 8
## Volvo 142E 21.4 4 121.0 109 4.11 2.780 18.60 1 1 4 2
library(ggplot2)
ggplot(data=mtcars, aes(x=cyl)) +
geom_histogram(aes(y=..density.., fill=..count..)) +
scale_fill_gradient(low = "lightblue", high = "blue") +
stat_function(fun=dnorm, colour = "red", args = list(mean(mtcars$cyl),
sd=sd(mtcars$cyl))) +
ggtitle("Histograma con curva normal teórica")
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
library(ggplot2)
ggplot(data=mtcars, aes(x=disp)) +
geom_histogram(aes(y=..density.., fill=..count..)) +
scale_fill_gradient(low = "lightgreen", high = "darkgreen") +
stat_function(fun=dnorm, colour = "white", args = list(mean(mtcars$disp),
sd=sd(mtcars$disp))) +
ggtitle("Histograma con curva normal teórica")
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
# Contraste qqplot para mpg
#=================================
qqnorm(mtcars$mpg, pch=19, col="blue")
qqline(mtcars$mpg)
# Contraste qqplot para cyl
#=================================
qqnorm(mtcars$cyl, pch=19, col="orange")
qqline(mtcars$cyl)
# Contraste qqplot para disp
#=================================
qqnorm(mtcars$disp, pch=19, col="pink")
qqline(mtcars$disp)
A continuación, se muestran los test de hipótesis más empleados para analizar la normalidad de los datos. En todos ellos, se considera como hipótesis nula que los datos sí proceden de una distribución normal y como hipótesis alternativa que no lo hacen. El p-value de estos test indica la probabilidad de obtener una distribución como la observada si los datos proceden realmente de una población con una distribución normal.
Cuando estos test se emplean con la finalidad de verificar las condiciones de métodos parámetricos, por ejemplo un t-test o un ANOVA, es importante tener en cuenta que, al tratarse de p-values, cuanto mayor sea el tamaño de la muestra más poder estadístico tienen y más fácil es encontrar evidencias en contra de la H0 (normalidad).
Al mismo tiempo, cuanto mayor sea el tamaño de la muestra, menos sensibles son los métodos paramétricos a la falta de normalidad. Por esta razón, es importante no basar las conclusiones únicamente en el p-value del test, sino también considerar la representación gráfica y el tamaño de la muestra.
Se recomienda usar el test de normalidad shapiro wilks si la muestra tiene n<50.
shapiro.test(x=mtcars$mpg)
##
## Shapiro-Wilk normality test
##
## data: mtcars$mpg
## W = 0.94756, p-value = 0.1229
shapiro.test(x=mtcars$cyl)
##
## Shapiro-Wilk normality test
##
## data: mtcars$cyl
## W = 0.75331, p-value = 6.058e-06
shapiro.test(x=mtcars$disp)
##
## Shapiro-Wilk normality test
##
## data: mtcars$disp
## W = 0.92001, p-value = 0.02081
Para mpg el p valor es 0.1229 > 0.05. tenemos evidencia empírica para aceptar la hipótesis de normalidad al 5%.
Para cyl el p valor es 0.000 < 0.05. Tenemos eidencia empírica suficiente para rechazar la hipótesis de normalidad al 5%.
Para disp el p valor es 0.02 siendo mayor al 1%, en este caso se acepta la hipótesis de normalidad. En cambio, para un nivel de significación del 5% o del 10% se rechaza la hipótesis de normalidad.
ks.test(x=mtcars$mpg, "pnorm", mean(mtcars$mpg), sd(mtcars$mpg))
## Warning in ks.test.default(x = mtcars$mpg, "pnorm", mean(mtcars$mpg),
## sd(mtcars$mpg)): ties should not be present for the Kolmogorov-Smirnov test
##
## Asymptotic one-sample Kolmogorov-Smirnov test
##
## data: mtcars$mpg
## D = 0.1263, p-value = 0.687
## alternative hypothesis: two-sided
ks.test(x=mtcars$cyl, "pnorm", mean(mtcars$cyl), sd(mtcars$cyl))
## Warning in ks.test.default(x = mtcars$cyl, "pnorm", mean(mtcars$cyl),
## sd(mtcars$cyl)): ties should not be present for the Kolmogorov-Smirnov test
##
## Asymptotic one-sample Kolmogorov-Smirnov test
##
## data: mtcars$cyl
## D = 0.28242, p-value = 0.01214
## alternative hypothesis: two-sided
ks.test(x=mtcars$disp, "pnorm", mean(mtcars$disp), sd(mtcars$disp))
## Warning in ks.test.default(x = mtcars$disp, "pnorm", mean(mtcars$disp), : ties
## should not be present for the Kolmogorov-Smirnov test
##
## Asymptotic one-sample Kolmogorov-Smirnov test
##
## data: mtcars$disp
## D = 0.19473, p-value = 0.1765
## alternative hypothesis: two-sided
Para mpg el p valor es de 0.687 > 0.05. Tenemos evidencia empírica a favor de la distribución normal.
El p-valor de cyl es mayor al 1% para este nivel de significación y acepta la hipótesis de normalidad. No obstante, al 5% y al 10% no se aceptaría la hipótesis de normalidad.
El p valor de disp es 0.1765 > 0.05. tenemos evidencia empírica para aceptar la hipótesis de normalidad.
library("nortest")
lillie.test(x= mtcars$mpg)
##
## Lilliefors (Kolmogorov-Smirnov) normality test
##
## data: mtcars$mpg
## D = 0.1263, p-value = 0.2171
lillie.test(x=mtcars$cyl)
##
## Lilliefors (Kolmogorov-Smirnov) normality test
##
## data: mtcars$cyl
## D = 0.28242, p-value = 5.796e-07
lillie.test(x=mtcars$disp)
##
## Lilliefors (Kolmogorov-Smirnov) normality test
##
## data: mtcars$disp
## D = 0.19473, p-value = 0.003328
En mpg el p-valor sigue aceptando la hipótesis de normalidad al 5%.
Pero las variables cyl y disp obtienen p-valores cercanos a cero, rechazando la hipótesis de normalidad para los niveles habituales de significación 1%, 5%, 10%).
library("tseries")
## Warning: package 'tseries' was built under R version 4.2.3
## Registered S3 method overwritten by 'quantmod':
## method from
## as.zoo.data.frame zoo
jarque.bera.test(x=mtcars$mpg)
##
## Jarque Bera Test
##
## data: mtcars$mpg
## X-squared = 2.2412, df = 2, p-value = 0.3261
jarque.bera.test(x=mtcars$cyl)
##
## Jarque Bera Test
##
## data: mtcars$cyl
## X-squared = 3.9464, df = 2, p-value = 0.139
jarque.bera.test(x=mtcars$disp)
##
## Jarque Bera Test
##
## data: mtcars$disp
## X-squared = 2.4377, df = 2, p-value = 0.2956
En los tests de Jarque-Bera se obtiene un p-valor por encima del 5%, se acepta la hipótesis de normalidad en todos los casos.
Hay que tener cuidado que el test Jarque-Bera es poco potente con pocos datos.
El hecho de no poder asumir la normalidad influye principalmente en los test de hipótesis paramétricos (t-test, anova,…) y en los modelos de regresión. Las principales consecuencias de la no normalidad son:
Los estimadores mínimo-cuadráticos no son eficientes (de mínima varianza).
Los intervalos de confianza de los parámetros del modelo y los contrastes de significancia son solamente aproximados y no exactos.
Los test estadísticos expuestos requieren que la población o poblaciones de las que proceden las muestras tengan una distribución normal, no que la las muestras en sí.
Si las muestras se distribuyen de forma normal, se puede aceptar que así lo hacen las poblaciones de origen. En el caso de que las muestras no se distribuyan de forma normal pero se tenga certeza de que las poblaciones de origen sí lo hacen, entonces, los resultados obtenidos por los contrastes paramétricos sí son válidos. El teorema del límite central, permite reducir los requerimientos de normalidad cuando las muestras son suficientemente grandes.
sesion_info <- devtools::session_info()
dplyr::select(
tibble::as_tibble(sesion_info$packages),
c(package, loadedversion, source)
)
## # A tibble: 75 × 3
## package loadedversion source
## <chr> <chr> <chr>
## 1 bslib 0.4.2 CRAN (R 4.2.2)
## 2 cachem 1.0.6 CRAN (R 4.2.2)
## 3 callr 3.7.3 CRAN (R 4.2.3)
## 4 cli 3.6.0 CRAN (R 4.2.2)
## 5 colorspace 2.1-0 CRAN (R 4.2.3)
## 6 crayon 1.5.2 CRAN (R 4.2.3)
## 7 curl 5.0.1 CRAN (R 4.2.3)
## 8 devtools 2.4.5 CRAN (R 4.2.3)
## 9 digest 0.6.31 CRAN (R 4.2.2)
## 10 dplyr 1.1.2 CRAN (R 4.2.3)
## # ℹ 65 more rows