La inferencia bayesiana combina información previa (prior) y evidencia de los datos (likelihood) para obtener una distribución posterior sobre el parámetro de interés: \[ p(\theta\mid y)\propto p(y\mid \theta)\,p(\theta). \] Una ventaja clave es el uso de familias conjugadas, donde prior y posterior pertenecen a la misma familia, facilitando el cálculo analítico.
Sea \(y_1,\dots,y_n\) una muestra Bernoulli con probabilidad de éxito \(\theta\): \[ y_i\mid \theta \sim \text{Bernoulli}(\theta), \qquad \text{o equivalentemente}\quad t=\sum_{i=1}^n y_i \mid \theta \sim \text{Binomial}(n,\theta). \] La verosimilitud para \(t\) es: \[ p(t\mid \theta)=\binom{n}{t}\theta^{t}(1-\theta)^{n-t}. \]
\[ \theta \sim \text{Beta}(a,b), \qquad p(\theta)\propto \theta^{a-1}(1-\theta)^{b-1}. \]
Multiplicando verosimilitud y prior: \[ p(\theta\mid t)\propto \theta^{t+a-1}(1-\theta)^{(n-t)+b-1}, \] por lo tanto: \[ \theta\mid t \sim \text{Beta}(a+t,\; b+n-t). \] Definiendo \(a' = a+t\) y \(b' = b+n-t\), se obtienen momentos: \[ \mathbb{E}[\theta\mid t]=\frac{a'}{a'+b'}, \qquad \mathrm{Var}(\theta\mid t)=\frac{a'b'}{(a'+b')^2(a'+b'+1)}. \]
Un intervalo creíble del \(95\%\) se obtiene con cuantiles de la Beta posterior: \[ \left[q_{\;0.025},q_{\;0.975}\right] = \left[ F^{-1}_{\text{Beta}(a',b')}(0.025), F^{-1}_{\text{Beta}(a',b')}(0.975) \right]. \]
Para una nueva observación \(y_{\text{new}}\): \[ \mathbb{P}(y_{\text{new}}=1\mid t)=\mathbb{E}[\theta\mid t]=\frac{a'}{a'+b'}. \] Para \(m\) ensayos futuros, \(T_{\text{new}}\mid t\) sigue una Beta–Binomial: \[ T_{\text{new}}\mid t \sim \text{BetaBinomial}(m,a',b'). \]
Sea \(y_1,\dots,y_n\) una muestra Poisson con tasa \(\lambda\): \[ y_i\mid \lambda \sim \text{Poisson}(\lambda), \qquad p(y_i\mid \lambda)=\frac{e^{-\lambda}\lambda^{y_i}}{y_i!}. \] La verosimilitud conjunta es: \[ p(\mathbf{y}\mid \lambda)\propto e^{-n\lambda}\lambda^{\sum_{i=1}^n y_i}. \] Defina \(S=\sum_{i=1}^n y_i\).
Usando parametrización Gamma por shape–rate: \[ \lambda \sim \text{Gamma}(\alpha,\beta), \qquad p(\lambda)\propto \lambda^{\alpha-1}e^{-\beta\lambda}. \]
\[ p(\lambda\mid \mathbf{y})\propto \left(e^{-n\lambda}\lambda^{S}\right)\left(\lambda^{\alpha-1}e^{-\beta\lambda}\right) = \lambda^{(\alpha+S)-1}e^{-(\beta+n)\lambda}, \] por lo tanto: \[ \lambda\mid \mathbf{y}\sim \text{Gamma}(\alpha+S,\;\beta+n). \] Momentos: \[ \mathbb{E}[\lambda\mid \mathbf{y}] = \frac{\alpha+S}{\beta+n}, \qquad \mathrm{Var}(\lambda\mid \mathbf{y}) = \frac{\alpha+S}{(\beta+n)^2}. \]
Para una nueva cuenta \(y_{\text{new}}\), la distribución predictiva marginal es Negativo Binomial: \[ p(y_{\text{new}}\mid \mathbf{y})=\int p(y_{\text{new}}\mid \lambda)p(\lambda\mid \mathbf{y})\,d\lambda, \] y se obtiene: \[ y_{\text{new}}\mid \mathbf{y}\sim \text{NegBin}\left(r=\alpha+S,\; p=\frac{\beta+n}{\beta+n+1}\right), \] bajo la convención donde: \[ \mathbb{P}(Y=k)=\binom{k+r-1}{k}(1-p)^k p^{r},\quad k=0,1,2,\dots \] Además, \[ \mathbb{E}[y_{\text{new}}\mid \mathbf{y}] = \mathbb{E}[\lambda\mid \mathbf{y}] = \frac{\alpha+S}{\beta+n}. \]
Beta–Binomial: \[ \theta\sim \text{Beta}(a,b),\quad t\mid\theta\sim \text{Bin}(n,\theta) \Rightarrow \theta\mid t\sim \text{Beta}(a+t,\; b+n-t). \]
Gamma–Poisson: \[ \lambda\sim \text{Gamma}(\alpha,\beta),\quad y_i\mid\lambda\sim \text{Pois}(\lambda) \Rightarrow \lambda\mid \mathbf{y}\sim \text{Gamma}(\alpha+\sum y_i,\; \beta+n). \]
library(ggplot2)
## Warning: package 'ggplot2' was built under R version 4.4.3
library(dplyr)
## Warning: package 'dplyr' was built under R version 4.4.3
##
## Adjuntando el paquete: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
set.seed(123)
# Muestra
y <- rbinom(10, 1, 0.4)
n <- length(y)
t <- sum(y)
# Prior
a <- 3
b <- 1
# Posterior
ap <- a + t
bp <- b + (n - t)
# Soporte
x <- seq(0.001, 0.999, by = 0.001)
df_plot <- bind_rows(
# Previas
data.frame(
x = x,
densidad = dbeta(x, 1, 1),
grupo = "Previa",
etiqueta = "Beta(1,1)"
),
data.frame(
x = x,
densidad = dbeta(x, 2, 2),
grupo = "Previa",
etiqueta = "Beta(2,2)"
),
data.frame(
x = x,
densidad = dbeta(x, 4, 4),
grupo = "Previa",
etiqueta = "Beta(4,4)"
),
# Prior
data.frame(
x = x,
densidad = dbeta(x, a, b),
grupo = "Prior vs Posterior",
etiqueta = "Prior"
),
# Posterior
data.frame(
x = x,
densidad = dbeta(x, ap, bp),
grupo = "Prior vs Posterior",
etiqueta = "Posterior"
)
)
ggplot(df_plot, aes(x = x, y = densidad, color = etiqueta)) +
geom_line(linewidth = 1.1) +
facet_wrap(~ grupo, scales = "free_y") +
labs(
title = "Modelo Beta-Binomial",
x = expression(theta),
y = "Densidad"
) +
theme_minimal() +
theme(
legend.position = "bottom",
strip.text = element_text(face = "bold")
)
# Muestra
y<-rbinom(10,1,0.4)
y
## [1] 1 0 1 0 0 1 0 0 0 1
# Previa
a<-1
b<-1
x<-seq(0.01,0.99,by=0.01)
betax<-dbeta(x,a,b)
plot(x,betax,type="l",col=3)
a<-2
b<-2
x<-seq(0.01,0.99,by=0.01)
betax<-dbeta(x,a,b)
plot(x,betax,type="l",col=3)
a<-4
b<-4
x<-seq(0.01,0.99,by=0.01)
betax<-dbeta(x,a,b)
plot(x,betax,type="l",col=3)
#Previa
# Historicamente 3 exitos por cada un fracaso
# Hiperparámetros
a<-3
b<-1
n<-length(y)
n
## [1] 10
t<-sum(y)
t
## [1] 4
# Métdo de Monte Carlo
theta_p<-rbeta(100000,a+t,b+n-t)
mean(theta_p)
## [1] 0.5003136
(a+t)/(a+b+n)
## [1] 0.5
ap<-a+t
bp<-b+n-t
var(theta_p)
## [1] 0.01665372
(ap*bp)/((ap+bp)**2*(ap+bp+1))
## [1] 0.01666667
#Intervalo de credibilidad
c(qbeta(0.025,ap,bp),qbeta(0.975,ap,bp))
## [1] 0.2513455 0.7486545
# Probailidad de cofnianza del 95%
# =========================================
# =========================================
# MODELO GAMMA - EJEMPLO COMPLETO (CORREGIDO)
# =========================================
# Librerias
library(ggplot2)
library(dplyr)
library(MASS) # fitdistr()
## Warning: package 'MASS' was built under R version 4.4.3
##
## Adjuntando el paquete: 'MASS'
## The following object is masked from 'package:dplyr':
##
## select
set.seed(123)
# -------------------------
# 1) Datos simulados (verdadero)
# -------------------------
shape_true <- 3.0
rate_true <- 0.8
scale_true <- 1 / rate_true
n_sim <- 800
x_sim <- rgamma(n_sim, shape = shape_true, rate = rate_true)
# -------------------------
# 2) Datos "historicos" (ejemplo)
# -------------------------
n_hist <- 500
x_hist <- rgamma(n_hist, shape = 2.4, rate = 0.9)
df_raw <- bind_rows(
data.frame(x = x_sim, fuente = "Simulado"),
data.frame(x = x_hist, fuente = "Historico")
)
# -------------------------
# 3) Ajuste Gamma por MLE (historico)
# -------------------------
fit <- fitdistr(x_hist, densfun = "gamma")
## Warning in densfun(x, parm[1], parm[2], ...): Se han producido NaNs
shape_hat <- fit$estimate["shape"]
rate_hat <- fit$estimate["rate"]
scale_hat <- 1 / rate_hat
# -------------------------
# 4) Curvas teoricas
# -------------------------
x_grid <- seq(0, quantile(df_raw$x, 0.995), length.out = 800)
df_curve <- bind_rows(
data.frame(
x = x_grid,
densidad = dgamma(x_grid, shape = shape_true, rate = rate_true),
curva = "Densidad verdadera (simulada)"
),
data.frame(
x = x_grid,
densidad = dgamma(x_grid, shape = shape_hat, rate = rate_hat),
curva = "Densidad ajustada (MLE)"
)
)
# -------------------------
# 5) Grafico 1: Histograma + densidades
# -------------------------
p1 <- ggplot(df_raw, aes(x = x)) +
geom_histogram(aes(y = after_stat(density)),
bins = 40,
fill = "gray85",
color = "gray40") +
geom_line(data = df_curve,
aes(x = x, y = densidad, linetype = curva),
linewidth = 1.1) +
facet_wrap(~ fuente, scales = "free_y") +
labs(
title = "Modelo Gamma: Histograma y densidad teorica",
x = "x",
y = "Densidad"
) +
theme_minimal() +
theme(legend.position = "bottom")
print(p1)
# -------------------------
# 6) Grafico 2: ECDF vs CDF Gamma (historico)
# -------------------------
df_ecdf <- data.frame(x = sort(x_hist)) %>%
mutate(
ecdf = ecdf(x_hist)(x),
cdf_fit = pgamma(x, shape = shape_hat, rate = rate_hat)
)
p2 <- ggplot(df_ecdf, aes(x = x)) +
geom_line(aes(y = ecdf), linewidth = 1.1) +
geom_line(aes(y = cdf_fit),
linetype = "dashed",
linewidth = 1.1) +
labs(
title = "Historico: ECDF vs CDF Gamma ajustada",
x = "x",
y = "Probabilidad acumulada"
) +
theme_minimal()
print(p2)
# -------------------------
# 7) Grafico 3: Q-Q plot Gamma (historico)
# -------------------------
p <- ppoints(length(x_hist))
q_teo <- qgamma(p, shape = shape_hat, rate = rate_hat)
q_emp <- sort(x_hist)
df_qq <- data.frame(
q_teo = q_teo,
q_emp = q_emp
)
p3 <- ggplot(df_qq, aes(x = q_teo, y = q_emp)) +
geom_point(alpha = 0.7) +
geom_abline(linetype = "dashed", linewidth = 1.1) +
labs(
title = "Q-Q plot: Historico vs Gamma ajustada",
x = "Cuantiles teoricos (Gamma ajustada)",
y = "Cuantiles empiricos (historico)"
) +
theme_minimal()
print(p3)
# -------------------------
# 8) Simulacion predictiva desde Gamma ajustada
# -------------------------
n_pred <- 500
x_pred <- rgamma(n_pred, shape = shape_hat, rate = rate_hat)
df_pred <- data.frame(x = x_pred)
p4 <- ggplot(df_pred, aes(x = x)) +
geom_histogram(aes(y = after_stat(density)),
bins = 40,
fill = "gray85",
color = "gray40") +
geom_line(
data = data.frame(
x = x_grid,
densidad = dgamma(x_grid, shape = shape_hat, rate = rate_hat)
),
aes(x = x, y = densidad),
linewidth = 1.1
) +
labs(
title = "Predictivo: nuevas observaciones (Gamma ajustada)",
x = "x",
y = "Densidad"
) +
theme_minimal()
print(p4)
# -------------------------
# 9) Resumen teorico Gamma
# -------------------------
cat("\n--- Ley Gamma ---\n")
##
## --- Ley Gamma ---
cat("PDF: f(x) = (rate^shape / Gamma(shape)) * x^(shape-1) * exp(-rate*x)\n")
## PDF: f(x) = (rate^shape / Gamma(shape)) * x^(shape-1) * exp(-rate*x)
cat("Soporte: x > 0\n")
## Soporte: x > 0
cat("Media: shape / rate\n")
## Media: shape / rate
cat("Varianza: shape / rate^2\n")
## Varianza: shape / rate^2
cat("\n--- Parametros ajustados (MLE, historico) ---\n")
##
## --- Parametros ajustados (MLE, historico) ---
cat("shape =", shape_hat, "\n")
## shape = 2.743421
cat("rate =", rate_hat, "\n")
## rate = 1.004718
cat("media =", shape_hat / rate_hat, "\n")
## media = 2.730538
cat("var =", shape_hat / (rate_hat^2), "\n")
## var = 2.717715
rm(list = ls())
graphics.off()
# ---- Paquetes ----
# install.packages(c("ggplot2","dplyr","tidyr","scales"))
library(ggplot2)
library(dplyr)
library(tidyr)
library(scales)
## Warning: package 'scales' was built under R version 4.4.3
set.seed(20260118)
# ---- 1) Datos (simulados) ----
nA <- 200
nB <- 100
# Parametros en escala log
muA <- log(7.5) - 0.5*(0.55^2) # A mean ~ 7.5
sdA <- 0.55
muB <- log(9.5) - 0.5*(0.70^2) # B mean ~ 9.5
sdB <- 0.70
tA <- rlnorm(nA, meanlog = muA, sdlog = sdA)
tB <- rlnorm(nB, meanlog = muB, sdlog = sdB)
df <- tibble(
grupo = c(rep("A_NetCo", nA), rep("B_Partner", nB)),
horas = c(tA, tB)
)
# ---- 2) Descriptivo ----
desc <- df %>%
group_by(grupo) %>%
summarise(
n = n(),
mean = mean(horas),
median = median(horas),
sd = sd(horas),
p90 = quantile(horas, 0.90),
p95 = quantile(horas, 0.95),
.groups = "drop"
)
print(desc)
## # A tibble: 2 × 7
## grupo n mean median sd p90 p95
## <chr> <int> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 A_NetCo 200 7.29 6.44 4.25 11.7 15.6
## 2 B_Partner 100 9.09 7.56 6.37 16.0 18.7
# ---- 3) Modelo Bayesiano Lognormal por grupo ----
# y = log(horas) ~ Normal(mu, sigma^2)
# Priors conjugados: Normal-Inverse-Gamma
posterior_normal_NIG <- function(y, m0=0, k0=0.01, a0=2, b0=2, S=50000) {
n <- length(y)
ybar <- mean(y)
ss <- sum((y - ybar)^2)
kn <- k0 + n
mn <- (k0*m0 + n*ybar)/kn
an <- a0 + n/2
bn <- b0 + 0.5*ss + (k0*n*(ybar - m0)^2)/(2*kn)
sig2 <- 1 / rgamma(S, shape = an, rate = bn) # Inv-Gamma
mu <- rnorm(S, mean = mn, sd = sqrt(sig2/kn))
list(mu=mu, sig2=sig2)
}
yA <- log(df$horas[df$grupo == "A_NetCo"])
yB <- log(df$horas[df$grupo == "B_Partner"])
m0 <- log(8) # prior debil centrado en 8h
k0 <- 0.01
a0 <- 2
b0 <- 2
S <- 60000
postA <- posterior_normal_NIG(yA, m0=m0, k0=k0, a0=a0, b0=b0, S=S)
postB <- posterior_normal_NIG(yB, m0=m0, k0=k0, a0=a0, b0=b0, S=S)
muA_s <- postA$mu; s2A_s <- postA$sig2
muB_s <- postB$mu; s2B_s <- postB$sig2
# ---- 4) Metricas en horas (escala original) ----
# E[T]=exp(mu+0.5*sigma^2), median=exp(mu)
meanA_s <- exp(muA_s + 0.5*s2A_s)
meanB_s <- exp(muB_s + 0.5*s2B_s)
medianA_s <- exp(muA_s)
medianB_s <- exp(muB_s)
diff_mean_s <- meanB_s - meanA_s
ratio_mean_s <- meanB_s / meanA_s
summ <- function(x) c(
mean = mean(x),
median = median(x),
sd = sd(x),
q025 = unname(quantile(x, 0.025)),
q975 = unname(quantile(x, 0.975))
)
# Probabilidades (decision-friendly)
p_B_gt_A <- mean(diff_mean_s > 0)
p_diff_gt_1 <- mean(diff_mean_s > 1)
p_diff_gt_2 <- mean(diff_mean_s > 2)
p_ratio_gt_1_2 <- mean(ratio_mean_s > 1.2)
rope <- 0.5
p_in_rope <- mean(abs(diff_mean_s) <= rope)
cat("\n--- Posterior mean(T) in hours ---\n")
##
## --- Posterior mean(T) in hours ---
print(rbind(A = summ(meanA_s), B = summ(meanB_s)))
## mean median sd q025 q975
## A 7.372684 7.361959 0.3109553 6.797382 8.016328
## B 9.219177 9.178980 0.6479222 8.065194 10.613867
cat("\n--- Posterior median(T) in hours ---\n")
##
## --- Posterior median(T) in hours ---
print(rbind(A = summ(medianA_s), B = summ(medianB_s)))
## mean median sd q025 q975
## A 6.316006 6.312134 0.2473972 5.841867 6.816716
## B 7.526575 7.513791 0.4776428 6.630175 8.508300
cat("\n--- Posterior diff of means (B - A) in hours ---\n")
##
## --- Posterior diff of means (B - A) in hours ---
print(summ(diff_mean_s))
## mean median sd q025 q975
## 1.8464925 1.8095296 0.7201659 0.5189098 3.3690365
cat("\n--- Posterior ratio of means (B / A) ---\n")
##
## --- Posterior ratio of means (B / A) ---
print(summ(ratio_mean_s))
## mean median sd q025 q975
## 1.2526861 1.2460794 0.1029577 1.0675199 1.4734879
cat("\n--- Key probabilities ---\n")
##
## --- Key probabilities ---
cat(sprintf("P(B worse than A in mean) = %.4f\n", p_B_gt_A))
## P(B worse than A in mean) = 0.9975
cat(sprintf("P(diff > 1 hour) = %.4f\n", p_diff_gt_1))
## P(diff > 1 hour) = 0.8875
cat(sprintf("P(diff > 2 hours) = %.4f\n", p_diff_gt_2))
## P(diff > 2 hours) = 0.3961
cat(sprintf("P(ratio > 1.2) (>=20%% worse) = %.4f\n", p_ratio_gt_1_2))
## P(ratio > 1.2) (>=20% worse) = 0.6845
cat(sprintf("P(|diff| <= %.1f h) (ROPE) = %.4f\n", rope, p_in_rope))
## P(|diff| <= 0.5 h) (ROPE) = 0.0231
# ---- 5) Graficas de datos (SIN tildes para evitar utf8towcs) ----
p1 <- ggplot(df, aes(x=horas, fill=grupo)) +
geom_histogram(alpha=0.5, bins=30, position="identity") +
labs(title="Repair times (hours) - Histogram", x="Hours", y="Count") +
theme_minimal()
p2 <- ggplot(df, aes(x=horas, color=grupo)) +
geom_density(linewidth=1) +
labs(title="Repair times (hours) - Density", x="Hours", y="Density") +
theme_minimal()
p3 <- ggplot(df, aes(x=grupo, y=horas, fill=grupo)) +
geom_violin(alpha=0.5, trim=FALSE) +
geom_boxplot(width=0.15, outlier.alpha=0.3) +
labs(title="Distribution by group (violin + box)", x="", y="Hours") +
theme_minimal() +
theme(legend.position="none")
p4 <- ggplot(df, aes(x=horas, color=grupo)) +
stat_ecdf(linewidth=1) +
labs(title="ECDF (empirical CDF) by group", x="Hours", y="F(h)") +
theme_minimal()
print(p1); print(p2); print(p3); print(p4)
# ---- 6) Graficas del posterior ----
post_df <- tibble(diff_mean = diff_mean_s, ratio_mean = ratio_mean_s)
p5 <- ggplot(post_df, aes(x=diff_mean)) +
geom_density(linewidth=1) +
geom_vline(xintercept=0, linetype="dashed") +
geom_vline(xintercept=c(-rope, rope), linetype="dotted") +
labs(
title="Posterior: difference of means (B - A)",
subtitle=sprintf("P(B>A)=%.3f | P(|diff|<=%.1fh)=%.3f", p_B_gt_A, rope, p_in_rope),
x="Difference (hours)", y="Density"
) +
theme_minimal()
p6 <- ggplot(post_df, aes(x=ratio_mean)) +
geom_density(linewidth=1) +
geom_vline(xintercept=1, linetype="dashed") +
geom_vline(xintercept=1.2, linetype="dotted") +
labs(
title="Posterior: ratio of means (B / A)",
subtitle=sprintf("P(ratio>1)=%.3f | P(ratio>1.2)=%.3f", mean(ratio_mean_s>1), p_ratio_gt_1_2),
x="Ratio", y="Density"
) +
theme_minimal()
print(p5); print(p6)
# ---- 7) Posterior Predictive Check (PPC) on mean ----
S_ppc <- 8000
idx <- sample(seq_along(muA_s), S_ppc)
sigmaA <- sqrt(s2A_s[idx])
sigmaB <- sqrt(s2B_s[idx])
TrepA_mean <- numeric(S_ppc)
TrepB_mean <- numeric(S_ppc)
for(i in 1:S_ppc){
TrepA <- rlnorm(nA, meanlog = muA_s[idx[i]], sdlog = sigmaA[i])
TrepB <- rlnorm(nB, meanlog = muB_s[idx[i]], sdlog = sigmaB[i])
TrepA_mean[i] <- mean(TrepA)
TrepB_mean[i] <- mean(TrepB)
}
ppc <- tibble(
grupo = rep(c("A_NetCo","B_Partner"), each=S_ppc),
mean_rep = c(TrepA_mean, TrepB_mean)
)
obs_means <- df %>% group_by(grupo) %>% summarise(mean_obs = mean(horas), .groups="drop")
p7 <- ggplot(ppc, aes(x=mean_rep, fill=grupo)) +
geom_density(alpha=0.5) +
geom_vline(data=obs_means, aes(xintercept=mean_obs), linetype="dashed") +
labs(title="PPC: distribution of replicated mean", x="Replicated mean (hours)", y="Density") +
theme_minimal()
print(p7)
bayes_p_A <- mean(TrepA_mean >= obs_means$mean_obs[obs_means$grupo=="A_NetCo"])
bayes_p_B <- mean(TrepB_mean >= obs_means$mean_obs[obs_means$grupo=="B_Partner"])
cat("\n--- PPC Bayesian p-values for mean ---\n")
##
## --- PPC Bayesian p-values for mean ---
cat(sprintf("Group A: %.3f\n", bayes_p_A))
## Group A: 0.551
cat(sprintf("Group B: %.3f\n", bayes_p_B))
## Group B: 0.520
# ---- 8) Ejemplo regla tipo regulador ----
# "Sancionar si P(diff > 2h) > 0.95"
decision <- ifelse(p_diff_gt_2 > 0.95, "STRONG evidence (intervene)", "Not enough evidence")
cat("\nDecision rule: if P(diff>2h)>0.95 => ", decision, "\n")
##
## Decision rule: if P(diff>2h)>0.95 => Not enough evidence