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:FF0

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:FN(0,1)

  • H0 compuesta: {H0:F=N(μ,σ2)H1:FN(μ,σ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=[Lk1,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[Lk1,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(LkLk1)

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ón nclass.xxx() donde xxx 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 a FALSE 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:

datos <- c(22.56,22.33,24.58,23.14,19.03,26.76,18.33,23.10,
  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().

Convergencia del histograma a la densidad teórica.

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)=1nni=11(Xix) 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:

fn <- ecdf(datos)
curve(ecdf(datos)(x), xlim = extendrange(datos), type = 's', 
      ylab = 'distribution function', lwd = 2)
curve(pnorm(x, mean(datos), sd(datos)), add = TRUE)
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.

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)=ni=11{Xix}B(n,F(x)),E(nFn(x))=nF(x)E(Fn(x))=F(x),Var(nFn(x))=nF(x)(1F(x))Var(Fn(x))=F(x)(1F(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=F10(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:FF0 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(XCi) 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 [Lk1,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, fipi. Equivalentemente, las frecuencias observadas ni=nfi deberían ser próximas a las esperadas ei=npi bajo H0, sugiriendo el estadístico del contraste (Pearson, 1900): χ2=ki=1(niei)2eiaprox.χ2kr1, 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 (niei)2ei
C1 n1 p1 e1 (n1e1)2e1
Ck nk pk ek (nkek)2ek
Total ini=n ipi=1 iei=n χ2=ki=1(niei)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: ki=1(niei)2eiχ2kr1,1α

Si realizamos el contraste a partir del p-valor o nivel crítico: p=P(χ2kr1ki=1(niei)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:

x <- trunc(5 * runif(100))
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=npi 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 ei5 consiste en tomar un número de intervalos kn/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:

simres::chisq.cont.test
## 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

  1. Típicamente \left \{ p_{i}=\frac{\left(i-0.5 \right)}n : i=1, \cdots, n \right\}.↩︎