El siguiente ejercicio se ubica en la Obervación 8 de las notas de clase. Se generaron mil números aleatorios y aplicando el item f) de la Parte 1 del Teorema 1.2: se simularon mil variables Gumbel standard \(iid\), calculándose su promedio, su desviación standard empírica y su mediana empírica.
## Observación 8:
# Fijar semilla para reproducibilidad
set.seed(123)
# Definir parámetros
mu <- 0 # Centro
beta <- 1 # Escala
gamma <- 0.5772156649 # Constante de Euler-Mascheroni
1- Simulación de los datos
# Número de simulaciones
n <- 1000
# Generar 1000 valores de una variable uniforme en (0,1)
U <- runif(n)
2- Definimos la variable Gumbel con los parámetros y los datos ya creados
# Simular la variable Gumbel con parámetros (mu, beta)
X_gumbel <- mu- beta * log(-log(U))
3- Calculamos las principales medidas estadísticas teóricas
esperanza <- mu + beta * gamma
moda <- mu
mediana_teorica <- mu- beta * log(log(2))
desviacion_std_teorica <- beta * pi / sqrt(6)
4- Calcular estadísticas empíricas
promedio_empirico <- mean(X_gumbel)
desviacion_std_empirica <- sd(X_gumbel)
mediana_empirica <- median(X_gumbel)
Los resultados fueron los siguientes:
## ----- Resultados teóricos: -----
## Esperanza teórica: 0.5772157
## Moda teórica: 0
## Mediana teórica: 0.3665129
## Desviación estándar teórica: 1.28255
## ----- Resultados empíricos (simulación con n = 1000 ): -----
## Promedio empírico: 0.5610296
## Mediana empírica: 0.3376409
## Desviación estándar empírica: 1.261928
Observar que los resultados empíricos están cerca del valor esperado, desvío standard y mediana de la Gumbel standard.
Imaginemos que se cuenta con los siguientes parámetros conocidos para unos determinados datos y sabemos que su distribución es Fréchet. En la página 13 de las notas de clase pueden encontrar cómo calcular los principales estadísticos descriptivos para cada distribución extremal.
# Parámetros
alpha <- 1.04 # alpha > 1
mu <- -6.5
beta <- 44
# 1) Media y mediana teóricas
mean_theo <- mu + beta * gamma(1 - 1/alpha)
median_theo <- mu + beta * (log(2))^(-1/alpha)
c(media_teorica = mean_theo, mediana_teorica = median_theo)
## media_teorica mediana_teorica
## 1113.71960 56.09002
Siguiendo el Teorema de los Teorema 6.2 (Apéndice) de los tipos de extremales. Si \(\exists\) las secuencias de constantes \(\left\{ a_n \right\}\) y \(\left\{ b_n \right\}\) tal que
\[ \Pr\{M^{\ast}_n \leq z\} \to G(z) \quad\text{a medida que}\quad n\to\infty \]
siendo \(G\) una función de distribución no degenerada, entonces \(G\) pertenece a una de las 3 siguientes familias:
\[\begin{align} \begin{array}{rcl} 1)\;G(z) & = & \exp\left\{ -\exp\left[-\left( \frac{z-b}{a} \right) \right] \right\}, \quad-\infty< z < \infty \\ \\ 2)\;G(z)& = & \left\{ \begin{array}{cl} 0 & ,\quad z\leq b\\ \exp\left\{ -\left( \frac{z-b}{a} \right)^{-\alpha} \right\} & , \quad z>b \end{array} \right. \\ \\ 3)\;G(z) & = &\left\{ \begin{array}{cl} \exp\left\{ -\left[ -\left( \frac{z-b}{a} \right)^{\alpha}\right] \right\} & , \quad z< b \\ 1 & , \quad z \geq b \end{array} \right. \end{array} \end{align}\]
para parámetros \(a>0\), \(b\), y en los casos 2) y 3) para \(\alpha >0\).
frechet_cdf <- function(x, alpha, mu, beta) {
ifelse(x > mu,
exp(-((x - mu) / beta)^(-alpha)),
0)
}
# install.packages("evd") # si hace falta
library(evd)
## Warning: package 'evd' was built under R version 4.3.3
set.seed(123)
x <- rfrechet(200, loc = mu, scale = beta, shape = alpha)
length(x)
## [1] 200
mean_sim <- mean(x)
median_sim <- median(x)
c(media_muestral = mean_sim, mediana_muestral = median_sim)
## media_muestral mediana_muestral
## 248.22969 49.96524
Veamos un ejemplo de ajuste. Los siguientes datos corresponden a los valores, en \(80\) puntos geográficos distintos de la región parisina, del máximo estival del contaminante atmosférico \(O_3\) (no perceptible sensorialmente y con impacto sanitario serio). Cada dato es el máximo registro en cada sensor a lo largo de todo un verano; el contaminante se mide diariamente, por lo cual, cada uno de nuestros \(80\) datos es el máximo de unas \(100\) lecturas diarias.
O3 = c(430.3, 115.7, 4.48, 26.95, 72.27, 206.4, 22.79, 25.03, 226.8, 11.1,
1572, 100, 104.5, 37.1, 20.22, 106.9, 47.2, 62.82, 39.3, 18.52,
41.47, 429.5, 1228, 127.6, 9.93, 90.4, 201.7, 295.1, 20.62, 20.58,
13.27, 538.1, 804, 321.6, 16.11, 22.05, 100.2, 40.76, 262.7, 19.32,
7.79, 58.02, 28.02, 18.38, 13.12, 572.8, 44.46, 40.72, 25.07, 24.07,
511.8, 38.12, 15.86, 75.48, 24.09, 119.4, 174.7, 104.7, 140, 79.67,
158, 25.46, 462.5, 35.53, 876.4, 462.5, 53.47, 23.59, 38.77, 494.2,
164.2, 52.06, 54.13, 15.53, 29, 14.35, 1675, 15.01, 72.07, 22.99)
length(O3)
## [1] 80
Los valores se miden en unidades de referencia standarizadas que, en particular, permiten comparar las medidas de lugares diferentes, independientemente de variables relevantes como altura e incidencia solar, por trabajo previo de calibración.
El objetivo del estudio en esta etapa es conocer la distribución de estos datos y en particular estimar la probabilidad de que el máximo estival en los 80 puntos supere el valor 50 (correspondiente a existencia de riesgo moderado).
Veamos los datos que tenemos:
1- Obtener los estadísticos básicos
# Cálculo de estadísticos básicos
summary(O3)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 4.48 23.44 52.77 183.93 166.82 1675.00
2- Graficar los datos del estudio
plot(O3, main="Máximos diarios de O3 en la región Parisina")
Vemos que hay algunos datos de máximos que se disparan, brindando pistas claras sobre la DEA candidata.
Como la mayoría de tests de ajustes suponen datos \(iid\), realizaremos dos tests de aleatoriedad1:
Runs test (Up & Down) : detecta si la dirección de cambio (sube/baja) ocurre al azar o en episodios persistentes (runs tests en R).
Spearman correlation of ranks : contrasta relación monótona; en series, suele usarse contra el tiempo (tendencia) o dependencia serial monótona (Spearman correlation of ranks en R).
La prueba de rachas es un método estadístico sencillo para analizar la aleatoriedad de una secuencia de datos. Permite determinar si los datos fluctúan de manera aleatoria o si presentan patrones o tendencias sistemáticas.
Una prueba de rachas evalúa si una secuencia de datos es aleatoria o
sigue un patrón sistemático examinando la aparición de rachas.
Una racha es una sucesión consecutiva de valores similares, por ejemplo:
altos y bajos, éxitos y fracasos, o cualquier otro resultado
binario.
3- Aplicamos la prueba de rachas
Esto lo haremos con la función run.tests del paquete
tseries.
# librería que precisamos
# Si no al tenemos, corremos en la consola: install.packages("tseries")
library(tseries)
## Registered S3 method overwritten by 'quantmod':
## method from
## as.zoo.data.frame zoo
Esta prueba busca aleatoriedad en la serie de datos observada examinando la frecuencia de rachas. Una racha se define como una secuencia consecutiva de respuestas similares.
# (a) Runs up and down
x <- as.numeric(O3)
thr <- 50 # umbral de interés
# Manejo de empates con el umbral
sum(x == thr, na.rm = TRUE) # cuántos empates hay?
## [1] 0
# 1 = excede 50, 0 = no excede
binarios <- as.integer(x > thr)
binarios
## [1] 1 1 0 0 1 1 0 0 1 0 1 1 1 0 0 1 0 1 0 0 0 1 1 1 0 1 1 1 0 0 0 1 1 1 0 0 1 0
## [39] 1 0 0 1 0 0 0 1 0 0 0 0 1 0 0 1 0 1 1 1 1 1 1 0 1 0 1 1 1 0 0 1 1 1 1 0 0 0
## [77] 1 0 1 0
# Test bilateral (aleatoriedad en general)
library(randtests)
## Warning: package 'randtests' was built under R version 4.3.3
##
## Attaching package: 'randtests'
## The following object is masked from 'package:tseries':
##
## runs.test
runs_test_result=tseries::runs.test(as.factor(binarios))
Resultado:
## p-valor (runs up and down): 0.8174643
Considerando un nivel de confianza del \(95\%\), o sea, para un nivel de significación de \(\alpha=0.05\), se tiene que el \(p-valor > \alpha=0.05\). Con este resultado no se rechaza \(H_0\), la secuencia de subidas y bajadas es compatible con aleatoriedad; no hay evidencia de patrón sistemático en la dirección de los cambios. Vemos que no rechazamos la hipótesis nula de rachas. Continuando con la idea de ajustar una distribución extremal
Mide la relación monótona entre dos variables ranqueadas. A diferencia de la correlación de Pearson, no asume normalidad ni linealidad, por lo que es ideal para datos ordinales y asociaciones no lineales (pero monótonas).
La correlación de Spearman, denotada por \(\rho\), cuantifica la fuerza y dirección de la relación monótona entre dos variables ordenadas. Sus valores posibles son:
Dados los rangos de las dos variables, sea \(d_i\) la diferencia entre los rangos del par \(i\) y \(n\) el número de observaciones:
\[ \rho \;=\; 1 \;-\; \frac{6 \sum_{i=1}^{n} d_i^2}{n\,(n^2-1)} \, . \]
Nota sobre empates: Si hay empates en los datos, se
usan rangos promedio; R ajusta
automáticamente el cálculo.
4- Vamos a analizar: Spearman vs tiempo (tendencia monótona)
t <- seq_along(O3) # índice temporal 1,2,...,T
res_t <- cor.test(O3, t, method = "spearman", exact = FALSE)
res_t$estimate # rho de Spearman
## rho
## -0.007372289
res_t$p.value # p-valor
## [1] 0.9482514
Como el \(p\text{-valor}\ge 0.05=\alpha\) entonces no hay sin evidencia de relación monótona.
Interpretación de tus resultados:
Runs up and down: No se rechaza la hipótesis nula de aleatoriedad. La secuencia de datos no presenta un patrón sistemático de subidas o bajadas.
Spearman: No hay evidencia de correlación entre observaciones sucesivas.
Ambos tests son coherentes con la hipótesis de que los datos se comportan como independientes e idénticamente distribuidos (\(iid\)), lo cual justifica el uso de modelos estadísticos que requieren esta suposición.
Como cada dato de los 80 que disponemos es un máximo de un centenar de observaciones, intentaremos ajustarlos a una distribución extremal sabiendo que no necesariamente tendremos éxito.
Dado que visualmente se aprecian valores muy apartados, se presume una distribución de colas pesadas y por ese motivo se intenta un ajuste a una Fréchet.
5- ¿Qué tipo de distribución extremal le parece que capture esta dinámica de máximos? ¿como se refleja en el indice de una GEV?
# install.packages("extRemes")
library(extRemes)
## Warning: package 'extRemes' was built under R version 4.3.3
## Loading required package: Lmoments
## Warning: package 'Lmoments' was built under R version 4.3.3
## Loading required package: distillery
## Warning: package 'distillery' was built under R version 4.3.3
##
## Attaching package: 'extRemes'
## The following object is masked from 'package:evd':
##
## mrlplot
## The following objects are masked from 'package:stats':
##
## qqnorm, qqplot
library(evd)
fit_gev <- fevd(O3, type = "GEV", method = "MLE")
# Veamos el valor de los parametros ajustados por mve
fit_gev$results$par
## location scale shape
## 36.315990 40.724476 1.105284
La estimación de shape un número positivo, por lo que
estamos ante posibles colas pesadas (como se intuia de ver la figura de
los valores). Se estimó una Fréchet pues \(xi>0\).
summary(fit_gev)
##
## fevd(x = O3, type = "GEV", method = "MLE")
##
## [1] "Estimation Method used: MLE"
##
##
## Negative Log-Likelihood Value: 473.1844
##
##
## Estimated parameters:
## location scale shape
## 36.315990 40.724476 1.105284
##
## Standard Error Estimates:
## location scale shape
## 5.046716 7.303154 0.140930
##
## Estimated parameter covariance matrix.
## location scale shape
## location 25.46934274 32.1308282 -0.01548037
## scale 32.13082815 53.3360655 0.41678836
## shape -0.01548037 0.4167884 0.01986125
##
## AIC = 952.3688
##
## BIC = 959.5148
6- Calcular la probabilidad de excedencia para el valor 50:
# pgev: CDF de la GEV que devuelve directamente la probabilidad de excedencia
par <- fit_gev$results$par
p_exc_mod <- pgev(50, loc = par["location"], scale = par["scale"], shape = par["shape"],lower.tail = FALSE)
# lower.tail: Logical; if TRUE (default), probabilities are P[X <= x], otherwise, P[X > x]
as.numeric(p_exc_mod)
## [1] 0.528321
# Alternativamente: Con Fréchet (mismos datos, reparametrizados)
alpha <- 1/par["shape"]
muF <- par["location"] - par["scale"]/par["shape"]
betaF <- par["scale"]/par["shape"]
p_exc_fr <- 1 - pfrechet(50, loc = muF, scale = betaF, shape = alpha)
as.numeric(p_exc_fr)
## [1] 0.528321
Relación entre la GEV y la Fréchet para el caso \(\xi > 0\) (Coles, 2001):
GEV estándar con \(\xi > 0\): Su función de distribución es \(F_{\mathrm{GEV}}(x) = \exp\left( - \left[ 1 + \xi \frac{x - \mu}{\sigma} \right]^{-1/\xi} \right)\), definida para \(1 + \xi \frac{x - \mu}{\sigma} > 0\).
Fréchet: Su función de distribución se suele escribir como \(F_{\mathrm{Fr}}(x) = \exp\left( - \left( \frac{x - \mu_F}{\beta_F}\right)^{-\alpha} \right)\), definida para \(x > \mu_F\).
Equivalencia GEV y Fréchet: Cuando \(\xi > 0\), la GEV se expresa como a una Fréchet si definimos
\[ \alpha = \frac{1}{\xi}, \quad \mu_F = \mu - \frac{\sigma}{\xi}, \quad \beta_F = \frac{\sigma}{\xi}. \]
# Alternativamente: Con la función que definimos manualmente
F50_manual <- frechet_cdf(50, alpha, muF, betaF)
1 - F50_manual
## location
## 0.528321
Para realizar el ajuste utilizaremos un conocido test de ajuste de carácter general: el test \(\chi^2\) de ajuste. Este test requiere elegir una partición mas o menos arbitraria de la recta real en intervalos; sin embargo es importante que en cada intervalo caiga una cantidad suficiente de datos de la muestra; en este caso hemos tomado como extremos de los intervalos los quintiles empíricos de nuestra muestra. Una aclaración mucho más importante es que este test requiere estimar parámetros por el método de Máxima Verosimilitud Categórica, que da resultado distintos al método de Máxima Verosimilitud a secas. Este hecho es frecuentemente ignorado y presentado erróneamente en los textos y cursos básicos de Estadística.
# ----------------------------
#Creamos cortes (quintiles)
# ----------------------------
n <- length(O3)
breaks <- quantile(O3, probs = seq(0, 1, 0.2))
# O_i: frecuencia observada en el intervalo i
observed <- hist(O3, breaks = breaks, plot = FALSE)$counts
# ----------------------------
# Creamos la Log-verosimilitud categórica
# ----------------------------
loglik_cat <- function(par) {
alpha <- par[1]
mu <- par[2]
beta <- par[3]
if (alpha <= 0 || beta <= 0) return(1e10) # penalizar fuera del dominio
p <- diff(frechet_cdf(breaks, alpha, mu, beta))
p <- pmax(p, 1e-10) # evitar log(0)
-sum(observed * log(p)) # log-verosimilitud categórica negativa
}
Verosimilitud categórica para la distribución de Fréchet:
Sea \((\alpha, \mu, \beta)\) el vector de parámetros de la distribución de Fréchet con función de distribución
\[ F_{\alpha,\mu,\beta}(x) = \exp\left( -\left( \frac{x - \mu}{\beta} \right)^{-\alpha} \right), \quad x > \mu, \]
y
\[ F_{\alpha,\mu,\beta}(x) = 0 \quad \text{si} \quad x \le \mu. \]
Supongamos que los datos se encuentran agrupados en \(k\) intervalos
\[ [b_0, b_1),\ [b_1, b_2),\ \dots,\ [b_{k-1}, b_k), \]
donde \(b_0 < b_1 < \dots < b_k\) son los puntos de corte (breaks), y que
\[ n_i = \text{frecuencia observada en el intervalo } [b_{i-1}, b_i) \]
para \(i=1,\dots,k\).
La probabilidad de que una observación \(X\) caiga en la clase \(i\) es:
\[ p_i(\alpha,\mu,\beta) = F_{\alpha,\mu,\beta}(b_i) - F_{\alpha,\mu,\beta}(b_{i-1}), \]
con \(p_i > 0\).
La Log-verosimilitud categórica para estos datos agrupados es
\[ \ell(\alpha,\mu,\beta) = \sum_{i=1}^k n_i \log\left[ p_i(\alpha,\mu,\beta) \right]. \]
Como muchas funciones de optimización en R minimizan, se
trabaja con la log-verosimilitud negativa
\[ - \ell(\alpha,\mu,\beta) = - \sum_{i=1}^k n_i \log\left[ F_{\alpha,\mu,\beta}(b_i) - F_{\alpha,\mu,\beta}(b_{i-1}) \right]. \]
Además, se impone la restricción \(\alpha>0\) y \(\beta>0\); si no se cumple, la función devuelve un valor grande como penalización.
# ----------------------------
# Optimización de parámetros
# ----------------------------
alphaF=alpha
# Valores iniciales: manual
start_par <- c(alpha = alphaF, mu = muF, beta = betaF)
fit_cat <- optim(par = start_par, fn = loglik_cat,
method = "L-BFGS-B", # especifica un algoritmo quasi-Newton que permite restricciones de caja
lower = c(0.01, -100, 1), upper = c(10, 100, 1000))
Ese bloque es el ajuste de los parámetros de tu modelo de Fréchet por
máxima verosimilitud categórica, usando el optimizador
optim de R. La función resuelve el problema de
optimización:
\[ \hat{\theta} = \arg\min_{\theta \in D} \; \ell_{cat}(\theta), \]
donde \(\theta = (\alpha, \mu, \beta)\) y \(D\) es la región de parámetros factibles definida por las siguientes restricciones
\[ 0.01 \le \alpha \le 10, \quad -100 \le \mu \le 100, \quad 1 \le \beta \le 1000. \]
La función \(\ell_{cat}(\theta)\) devuelve la log-verosimilitud categórica negativa
\[ \ell_{cat}(\theta) = - \sum_{i=1}^k n_i \; \log\left[ F_{\theta}(b_i) - F_{\theta}(b_{i-1}) \right], \]
donde \(F_{\theta}\) es la CDF de Fréchet, \(b_i\) son los límites de clase y \(n_i\) las frecuencias observadas.
Estos son los parámetros estimados por MVC:
## alpha.shape mu.location beta.scale
## 0.9095229 0.1322393 35.9103648
Ahora con los parámetros estimados, se realiza el test \(\chi^2\):
# Parámetros estimados por MVC
alpha <- fit_cat$par["alpha.shape"]
mu <- fit_cat$par["mu.location"]
beta <- fit_cat$par["beta.scale"]
Calculamos las probabilidades por intervalo \(F_{\theta}(b_i) - F_{\theta}(b_{i-1})\)
# Probabilidades teóricas en cada intervalo (quintiles)
p_expected <- diff(frechet_cdf(breaks, alpha, mu, beta))
Acá, \(p_{\text{expected}}\) es el vector con las probabilidades \(p_i\) de que un dato caiga en cada intervalo
\[ p_i = F_{\theta}(b_i) - F_{\theta}(b_{i-1}), \quad i = 1, \dots, k \] Para pasar de probabilidades teóricas a frecuencias esperadas, calculamos
expected <- p_expected * n
Tenemos \[ p_i = P\big( b_{i-1} \le X < b_i \big) \] que es la probabilidad de caer en el intervalo \([b_{i-1}, b_i)\).
Tenemos \[ n = \text{tamaño total de la muestra}. \]
La frecuencia esperada en ese intervalo, si el modelo es correcto, es \[ E_i = n \cdot p_i. \] Calculamos el test de bondad de ajuste \(\chi^2\):
\[ \chi^2 = \sum_{i=1}^k \frac{(O_i - E_i)^2}{E_i} \]
donde
\(O_i = \text{frecuencia observada en el intervalo } i\),
\(E_i = \text{frecuencia esperada calculada como } E_i = n \cdot p_i\).
Testeamos las siguientes hipótesis:
\(H_0: \text{Los datos siguen la distribución de Fréchet con los parámetros estimados.}\)
\(H_1: \text{Los datos no siguen esa distribución.}\)
Conclusiones:
# Recalcular test Chi2
chi_sq <- sum((observed - expected)^2 / expected)
# Número de clases (categorías)
k <- length(observed)
# Número de parámetros estimados del modelo
m <- length(fit_cat$par)
# Grados de libertad
df <- k - 1 - m
p_val_chi <- 1 - pchisq(chi_sq, df) #pchisq: funcion de distribucion
Se obtiene como resultados:
## Chi2: 2.961947 gl: 1 p-valor: 0.08524526
Como \(p-valor > 0.05\), no se rechaza \(H_0\) al \(5\%\) de significancia.
En inglés es randomness.↩︎