A.1 Métodos de bondad de ajuste
A partir de X1,…,Xn m.a.s. de X con función de distribución F, interesa realizar un contraste de la forma: {H0:F=F0H1:F≠F0
En este caso interesará distinguir principalmente entre hipótesis nulas simples (especifican un único modelo) y compuestas (especifican un conjunto o familia de modelos). Por ejemplo:
H0 simple: {H0:F=N(0,1)H1:F≠N(0,1)
H0 compuesta: {H0:F=N(μ,σ2)H1:F≠N(μ,σ2)
Entre los métodos gráficos habituales estarían: histograma, gráfico de la densidad suavizada, gráfico de tallo y hojas, gráfico de la distribución empírica (o versión suavizada) y gráficos P-P o Q-Q.
Entre los métodos de contrastes de hipótesis generales (H0:F=F0) destacarían las pruebas: Chi-cuadrado de Pearson, Kolmogorov-Smirnov, Cramer-von Mises o Anderson-Darling. Además de los específicos de normalidad (H0:F=N(μ,σ2)): Kolmogorov-Smirnov-Lilliefors, Shapiro-Wilks y los de asimetría y apuntamiento.
A.1.1 Histograma
Se agrupan los datos en intervalos Ik=[Lk−1,Lk) con k=1,…,K y a cada intervalo se le asocia un valor (altura de la barra) igual a la frecuencia absoluta de ese intervalo nk=∑ni=11(Xi∈[Lk−1,Lk)), si la longitud de los intervalos es constante, o proporcional a dicha frecuencia (de forma que el área coincida con la frecuencia relativa y pueda ser comparado con una función de densidad): ˆfn(x)=nin(Lk−Lk−1)
Como ya se ha visto anteriormente, en R podemos generar este gráfico con la función hist()
del paquete base.
Algunos de los principales parámetros (con los valores por defecto) son los siguientes:
hist(x, breaks = "Sturges", freq = NULL, plot = TRUE, ...)
breaks
: puede ser un valor numérico con el número de puntos de discretización, un vector con los puntos de discretización, una cadena de texto que los determine (otras opciones son"Scott"
y"FD"
; en este caso llamará internamente a la funciónnclass.xxx()
dondexxx
se corresponde con la cadena de texto), o incluso una función personalizada que devuelva el número o el vector de puntos de discretización.freq
: lógico (TRUE
por defecto si los puntos de discretización son equidistantes), determina si en el gráfico se representan frecuencias o “densidades”.plot
: lógico, se puede establecer aFALSE
si no queremos generar el gráfico y solo nos interesan el objeto con los resultados (que devuelve de forma “invisible”, por ejemplo para discretizar los valores en intervalos).
Ejemplo:
<- c(22.56,22.33,24.58,23.14,19.03,26.76,18.33,23.10,
datos 21.53,9.06,16.75,23.29,22.14,16.28,18.89,27.48,10.44,
26.86,27.27,18.74,19.88,15.76,30.77,21.16,24.26,22.90,
27.14,18.02,21.53,24.99,19.81,11.88,24.01,22.11,21.91,
14.35,11.14,9.93,20.22,17.73,19.05)
hist(datos, freq = FALSE)
curve(dnorm(x, mean(datos), sd(datos)), add = TRUE)
Si el número de valores es muy grande (por ejemplo en el caso de secuencias aleatorias), nos puede interesar establecer la opción breaks = "FD"
para aumentar el número de intervalos de discretización.
En cualquier caso, como se muestra en la Figura A.1, la convergencia del histograma a la densidad teórica se podría considerar bastante lenta.
Alternativamente se podría considerar una estimación suave de la densidad, por ejemplo empleando la estimación tipo núcleo implementada en la función density()
.

Figura A.1: Convergencia del histograma a la densidad teórica.
A.1.2 Función de distribución empírica
La función de distribución empírica Fn(x)=1n∑ni=11(Xi≤x) asigna a cada número real x la frecuencia relativa de observaciones menores o iguales que x. Para obtener las frecuencias relativas acumuladas, se ordena la muestra X(1)≤X(2)≤⋯≤X(n) y: Fn(x)={0si x<X(1)insi X(i)≤x<X(i+1)1si X(n)≤x
En R podemos obtener la función de distribución empírica con ecdf()
(el objeto que devuelve es una función).
Ejemplo:
<- ecdf(datos)
fn curve(ecdf(datos)(x), xlim = extendrange(datos), type = 's',
ylab = 'distribution function', lwd = 2)
curve(pnorm(x, mean(datos), sd(datos)), add = TRUE)

Figura A.2: Comparación de la distribución empírica de los datos de ejemplo con la función de distribución de la aproximación normal.
La función de distribución empírica se corresponde con una variable aleatoria discreta que toma los valores X1,…,Xn todos ellos con probabilidad 1n. Suponiendo que X=(X1,…,Xn) es una muestra aleatoria de una población con distribución F: nFn(x)=n∑i=11{Xi≤x}∼B(n,F(x)),E(nFn(x))=nF(x)⟹E(Fn(x))=F(x),Var(nFn(x))=nF(x)(1−F(x))⟹Var(Fn(x))=F(x)(1−F(x))n
A.1.3 Gráficos P-P y Q-Q
El gráfico de probabilidad (o de probabilidad-probabilidad) es el gráfico de dispersión de: {(F0(xi),Fn(xi)):i=1,⋯,n} siendo Fn la función de distribución empírica y F0 la función de distribución bajo H0 (con la que desea comparar, si la hipótesis nula es simple) o una estimación bajo H0 (si la hipótesis nula es compuesta; e.g. si H0:F=N(μ,σ2), ˆF0 función de distribución de N(ˆμ,ˆσ2)). Si H0 es cierta, la nube de puntos estará en torno a la recta y=x (probabilidades observadas próximas a las esperadas bajo H0).
El gráfico Q-Q (cuantil-cuantil) es equivalente al anterior pero en la escala de la variable: {(qi,x(i)):i=1,⋯,n} siendo x(i) los cuantiles observados y qi=F−10(pi) los esperados44 bajo H0.
Ejemplo:
qqnorm(datos)
qqline(datos)
require(car)
qqPlot(datos, "norm")
## [1] 10 38
A.1.4 Contraste chi-cuadrado de Pearson
Se trata de un contraste de bondad de ajuste: {H0:F=F0H1:F≠F0 desarrollado inicialmente para variables categóricas. En el caso general, podemos pensar que los datos están agrupados en k clases: C1,⋯,Ck. Por ejemplo, si la variable es categórica o discreta, cada clase se puede corresponder con una modalidad. Si la variable es continua habrá que categorizarla en intervalos.
Si la hipótesis nula es simple, cada clase tendrá asociada una probabilidad pi=P(X∈Ci) bajo H0 . Si por el contrario es compuesta, se trabajará con una estimación de dicha probabilidad (y habrá que correguir la distribución aproximada del estadístico del contraste).
Clases | Discreta | Continua | H0 simple | H0 compuesta |
---|---|---|---|---|
C1 | x1 | [L0,L1) | p1 | ˆp1 |
⋮ | ⋮ | ⋮ | ⋮ | ⋮ |
Ck | xk | [Lk−1,Lk) | pk | ˆpk |
∑ipi=1 | ∑iˆpi=1 |
Se realizará un contraste equivalente: {H0:Las probabilidades son correctasH1:Las probabilidades no son correctas
Si H0 es cierta, la frecuencia relativa fi de la clase Ci es una aproximación de la probabilidad teórica, fi≈pi. Equivalentemente, las frecuencias observadas ni=n⋅fi deberían ser próximas a las esperadas ei=n⋅pi bajo H0, sugiriendo el estadístico del contraste (Pearson, 1900): χ2=k∑i=1(ni−ei)2ei∼aprox.χ2k−r−1, si H0 cierta siendo k el número de clases y r el número de parámetros estimados (para aproximar las probabilidades bajo H0).
Clases | ni observadas | pi bajo H0 | ei bajo H0 | (ni−ei)2ei |
---|---|---|---|---|
C1 | n1 | p1 | e1 | (n1−e1)2e1 |
⋮ | ⋮ | ⋮ | ⋮ | ⋮ |
Ck | nk | pk | ek | (nk−ek)2ek |
Total | ∑ini=n | ∑ipi=1 | ∑iei=n | χ2=∑ki=1(ni−ei)2ei |
Cuando H0 es cierta el estadístico tiende a tomar valores pequeños y grandes cuando es falsa. Por tanto se rechaza H0, para un nivel de significación α, si: k∑i=1(ni−ei)2ei≥χ2k−r−1,1−α
Si realizamos el contraste a partir del p-valor o nivel crítico: p=P(χ2k−r−1≥k∑i=1(ni−ei)2ei) rechazaremos H0 si p≤α (y cuanto menor sea se rechazará con mayor seguridad) y aceptaremos H0 si p> α (con mayor seguridad cuanto mayor sea).
Este método está implementado en la función chisq.test()
para el caso discreto (no corrige los grados de libertad).
Ejemplo:
<- trunc(5 * runif(100))
x chisq.test(table(x)) # NOT 'chisq.test(x)'!
##
## Chi-squared test for given probabilities
##
## data: table(x)
## X-squared = 3.1, df = 4, p-value = 0.54
La distribución exacta del estadístico del contraste es discreta (se podría aproximar por simulación, por ejemplo empleando los parámetros simulate.p.value = TRUE
y B = 2000
de la función chisq.test()
; ver también el Ejemplo 6.10 de la Sección 6.7.2 para el caso del contraste chi-cuadrado de independencia).
Para que la aproximación continua χ2 sea válida:
El tamaño muestral debe ser suficientemente grande (p.e. n>30).
La muestra debe ser una muestra aleatoria simple.
Los parámetros deben estimarse (si es necesario) por máxima verosimilitud.
Las frecuencias esperadas ei=n⋅pi deberían ser todas ≥5 (realmente esta es una restricción conservadora, la aproximación puede ser adecuada si no hay frecuencias esperadas inferiores a 1 y menos de un 20% inferiores a 5).
Si la frecuencia esperada de alguna clase es <5, se suele agrupar con otra clase (o con varias si no fuese suficiente con una) para obtener una frecuencia esperada ≥5:
Cuando la variable es nominal (no hay una ordenación lógica) se suele agrupar con la(s) que tiene(n) menor valor de ei.
Si la variable es ordinal (o numérica) debe juntarse la que causó el problema con una de las adyacentes.
Si la variable de interés es continua, una forma de garantizar que ei≥5 consiste en tomar un número de intervalos k≤⌊n/5⌋ y de forma que sean equiprobables pi=1/k, considerando los puntos críticos xi/k de la distribución bajo H0.
Por ejemplo, se podría emplear la función simres::chisq.cont.test()
(fichero test.R), que imita a las incluidas en R:
::chisq.cont.test simres
## function(x, distribution = "norm", nclass = floor(length(x)/5),
## output = TRUE, nestpar = 0, ...) {
## # Función distribución
## q.distrib <- eval(parse(text = paste("q", distribution, sep = "")))
## # Puntos de corte
## q <- q.distrib((1:(nclass - 1))/nclass, ...)
## tol <- sqrt(.Machine$double.eps)
## xbreaks <- c(min(x) - tol, q, max(x) + tol)
## # Gráficos y frecuencias
## if (output) {
## xhist <- hist(x, breaks = xbreaks, freq = FALSE,
## lty = 2, border = "grey50")
## # Función densidad
## d.distrib <- eval(parse(text = paste("d", distribution, sep = "")))
## curve(d.distrib(x, ...), add = TRUE)
## } else {
## xhist <- hist(x, breaks = xbreaks, plot = FALSE)
## }
## # Cálculo estadístico y p-valor
## O <- xhist$counts # Equivalente a table(cut(x, xbreaks)) pero más eficiente
## E <- length(x)/nclass
## DNAME <- deparse(substitute(x))
## METHOD <- "Pearson's Chi-squared test"
## STATISTIC <- sum((O - E)^2/E)
## names(STATISTIC) <- "X-squared"
## PARAMETER <- nclass - nestpar - 1
## names(PARAMETER) <- "df"
## PVAL <- pchisq(STATISTIC, PARAMETER, lower.tail = FALSE)
## # Preparar resultados
## classes <- format(xbreaks)
## classes <- paste("(", classes[-(nclass + 1)], ",", classes[-1], "]",
## sep = "")
## RESULTS <- list(classes = classes, observed = O, expected = E,
## residuals = (O - E)/sqrt(E))
## if (output) {
## cat("\nPearson's Chi-squared test table\n")
## print(as.data.frame(RESULTS))
## }
## if (any(E < 5))
## warning("Chi-squared approximation may be incorrect")
## structure(c(list(statistic = STATISTIC, parameter = PARAMETER, p.value = PVAL,
## method = METHOD, data.name = DNAME), RESULTS), class = "htest")
## }
## <bytecode: 0x0000019b309f5db8>
## <environment: namespace:simres>
Continuando con el ejemplo anterior, podríamos contrastar normalidad mediante:
library(simres)
chisq.cont.test(datos, distribution = "norm", nestpar = 2, mean=mean(datos), sd=sd(datos))
##
## Pearson's Chi-squared test table
## classes observed expected residuals
## 1 ( 9.060,14.499] 6 5.125 0.38651
## 2 (14.499,16.947] 3 5.125 -0.93867
## 3 (16.947,18.778] 4 5.125 -0.49694
## 4 (18.778,20.417] 6 5.125 0.38651
## 5 (20.417,22.057] 4 5.125 -0.49694
## 6 (22.057,23.887] 8 5.125 1.26996
## 7 (23.887,26.336] 4 5.125 -0.49694
## 8 (26.336,30.770] 6 5.125 0.38651
##
## Pearson's Chi-squared test
##
## data: datos
## X-squared = 3.68, df = 5, p-value = 0.6
A.1.5 Contraste de Kolmogorov-Smirnov
Se trata de un contraste de bondad de ajuste diseñado para distribuciones continuas
(similar a la prueba de Cramer-von Mises o a la de Anderson-Darling, implementadas en el paquete goftest
de R, que son en principio mejores).
Se basa en comparar la función de distribución F0 bajo H0 con la función de distribución empírica Fn:
Dn=sup
Teniendo en cuenta que F_n\left( X_{(i)}\right) = \frac{i}n: \begin{aligned} D_n & =\max_{1\leq i\leq n}\left \{ \frac{i}n-F_0(X_{(i)}),F_0(X_{(i)})-\frac{i-1}n\right \} \\ & =\max_{1\leq i\leq n}\left \{ D_{n,i}^{+},D_{n,i}^{-}\right \} \end{aligned}
Si H_0 es simple y F_0 es continua, la distribución del estadístico D_n bajo H_0 no depende F_0 (es de distribución libre).
Esta distribución está tabulada (para tamaños muestrales grandes se utiliza la aproximación asintótica).
Se rechaza H_0 si el valor observado d del estadístico es significativamente grande:
p = P \left( D_n \geq d \right) \leq \alpha.
Este método está implementado en la función ks.test()
del paquete base de R:
ks.test(x, y, ...)
donde x
es un vector que contiene los datos, y
es una función de distribución
(o una cadena de texto que la especifica; también puede ser otro vector de datos
para el contraste de dos muestras) y ...
representa los parámetros de la distribución.
Continuando con el ejemplo anterior, para contrastar H_0:F= \mathcal{N}(20,5^2) podríamos emplear:
ks.test(datos, pnorm, mean = 20, sd = 5) # One-sample
##
## Asymptotic one-sample Kolmogorov-Smirnov test
##
## data: datos
## D = 0.132, p-value = 0.47
## alternative hypothesis: two-sided
Si H_0 es compuesta, el procedimiento habitual es estimar los parámetros desconocidos por máxima verosimilitud y emplear \hat{F}_0 en lugar de F_0. Sin embargo, al proceder de esta forma es de esperar que \hat{F}_0 se aproxime más que F_0 a la distribución empírica, por lo que los cuantiles de la distribución de D_n pueden ser demasiado conservativos (los p-valores tenderán a ser mayores de lo que deberían) y se tenderá a aceptar la hipótesis nula (puede ser preferible aproximar el p-valor mediante simulación; como se muestra en el Ejercicio 7.6 de la Sección 7.4.3).
Para evitar este problema, en el caso de contrastar normalidad se desarrolló el test
de Lilliefors, implementado en la función lillie.test()
del paquete nortest
(también hay versiones en este paquete para los métodos de Cramer-von Mises y
Anderson-Darling).
Por ejemplo:
ks.test(datos, pnorm, mean(datos), sd(datos)) # One-sample Kolmogorov-Smirnov test
##
## Asymptotic one-sample Kolmogorov-Smirnov test
##
## data: datos
## D = 0.0978, p-value = 0.83
## alternative hypothesis: two-sided
library(nortest)
lillie.test(datos)
##
## Lilliefors (Kolmogorov-Smirnov) normality test
##
## data: datos
## D = 0.0978, p-value = 0.42
Típicamente \left \{ p_{i}=\frac{\left(i-0.5 \right)}n : i=1, \cdots, n \right\}.↩︎