Generar datos simulados para dos distribuciones (Normal y Exponencial) con n = 20 y R = 30 réplicas; calcular la media por réplica; construir y reportar intervalos de confianza (95%) para la media poblacional; comparar y discutir resultados; y (opcional) evidenciar que las medias se aproximan a la normalidad (CLT).
params <- list(
seed = 1234L,
n = 20L,
R = 30L,
mu_norm = 15,
sd_norm = 5,
mean_exp = 3.5
)
set.seed(params$seed)
params
## $seed
## [1] 1234
##
## $n
## [1] 20
##
## $R
## [1] 30
##
## $mu_norm
## [1] 15
##
## $sd_norm
## [1] 5
##
## $mean_exp
## [1] 3.5
ic_95_t <- function(v) {
m <- mean(v); s <- sd(v); N <- length(v)
se <- s / sqrt(N); t_crit <- qt(0.975, df = N - 1)
c(inf = m - t_crit * se, sup = m + t_crit * se)
}
ic_replica_t <- function(x, alpha = 0.05) {
n <- length(x)
m <- mean(x)
s <- sd(x)
se <- s / sqrt(n)
tcrit <- qt(1 - alpha/2, df = n - 1)
c(inf = m - tcrit * se, sup = m + tcrit * se)
}
# Normal(mu=15, sd=5)
medias_normal <- replicate(params$R, mean(rnorm(params$n, params$mu_norm, params$sd_norm)))
# Exponencial(media=3.5) -> rate = 1/mean
medias_expon <- replicate(params$R, mean(rexp(params$n, rate = 1/params$mean_exp)))
# Tabla con las 30 medias para ambas distribuciones (para entregar)
tabla_medias <- data.frame(
replica = 1:params$R,
media_normal = medias_normal,
media_exponencial = medias_expon
)
knitr::kable(head(tabla_medias, 10), digits = 4, caption = "Primeras 10 de las 30 medias por réplica.")
| replica | media_normal | media_exponencial |
|---|---|---|
| 1 | 13.7467 | 2.8079 |
| 2 | 12.1147 | 3.0537 |
| 3 | 12.7783 | 3.2202 |
| 4 | 16.4357 | 3.0322 |
| 5 | 16.0056 | 3.7062 |
| 6 | 14.4347 | 4.9138 |
| 7 | 14.4913 | 3.2757 |
| 8 | 16.1786 | 2.5248 |
| 9 | 16.0935 | 2.6494 |
| 10 | 14.8330 | 2.9433 |
write.csv(tabla_medias, file.path(out_dir, "tabla_medias_30_replicas.csv"), row.names = FALSE)
ic_norm <- ic_95_t(medias_normal)
ic_exp <- ic_95_t(medias_expon)
resumen <- data.frame(
Distribución = c("Normal(15,5)", "Exponencial(media=3.5)"),
n_replicas = c(params$R, params$R),
`Media de las medias` = c(mean(medias_normal), mean(medias_expon)),
`Desviación estándar de las medias` = c(sd(medias_normal), sd(medias_expon)),
IC95_inferior = c(ic_norm["inf"], ic_exp["inf"]),
IC95_superior = c(ic_norm["sup"], ic_exp["sup"])
)
knitr::kable(resumen, digits = 4, caption = "IC 95% para la media poblacional (vía t-Student aplicado a las 30 medias).")
| Distribución | n_replicas | Media.de.las.medias | Desviación.estándar.de.las.medias | IC95_inferior | IC95_superior |
|---|---|---|---|---|---|
| Normal(15,5) | 30 | 14.8936 | 1.1729 | 14.4556 | 15.3316 |
| Exponencial(media=3.5) | 30 | 3.4837 | 0.6542 | 3.2394 | 3.7280 |
write.csv(resumen, file.path(out_dir, "resumen_IC_95.csv"), row.names = FALSE)
hist(medias_normal, breaks = 8, main = "Medias (30 réplicas) - Normal(15,5)",
xlab = "Media por réplica", ylab = "Frecuencia")
xseq <- seq(min(medias_normal), max(medias_normal), length.out = 200)
dens <- dnorm(xseq, mean = mean(medias_normal), sd = sd(medias_normal))
dens <- dens * diff(hist(medias_normal, plot = FALSE)$breaks)[1] * length(medias_normal)
lines(xseq, dens, lwd = 2)
qqnorm(medias_normal, main = "QQ-plot de medias - Normal(15,5)")
qqline(medias_normal, col = "red", lwd = 2)
hist(medias_expon, breaks = 8, main = "Medias (30 réplicas) - Exponencial(media=3.5)",
xlab = "Media por réplica", ylab = "Frecuencia")
xseq <- seq(min(medias_expon), max(medias_expon), length.out = 200)
dens <- dnorm(xseq, mean = mean(medias_expon), sd = sd(medias_expon))
dens <- dens * diff(hist(medias_expon, plot = FALSE)$breaks)[1] * length(medias_expon)
lines(xseq, dens, lwd = 2)
qqnorm(medias_expon, main = "QQ-plot de medias - Exponencial(media=3.5)")
qqline(medias_expon, col = "red", lwd = 2)
Nota: Si no cuentas con ProModel/Stat:fit, aquí justificamos la normalidad de las medias con QQ-plots y Shapiro; además, dejamos la visual IC por réplica y cobertura como apoyo didáctico.
En esta sección se construyen 30 IC (95%) por réplica a partir de los datos crudos de cada muestra (tamaño \(n=20\)), y se reporta la tasa de cobertura con respecto a la media verdadera.
build_replica_intervals <- function(R, n, gen_fun, true_mean, out_prefix, ...) {
ICs <- matrix(NA_real_, nrow = R, ncol = 2, dimnames = list(NULL, c("inf","sup")))
means <- numeric(R)
for (r in 1:R) {
x <- gen_fun(n, ...)
means[r] <- mean(x)
ICs[r,] <- ic_replica_t(x)
}
coverage <- (ICs[,1] <= true_mean) & (true_mean <= ICs[,2])
cov_rate <- mean(coverage)
df <- data.frame(replica = 1:R, media = means, IC_inf = ICs[,1], IC_sup = ICs[,2], cubre = coverage)
write.csv(df, file.path(out_dir, paste0(out_prefix, "_ICs_por_replica.csv")), row.names = FALSE)
plot(NA, xlim = range(ICs), ylim = c(0.5, R + 0.5),
xlab = "Intervalo de Confianza (95%)", ylab = "Réplica",
main = paste0("IC por réplica (95%) - ", out_prefix,
"\nCobertura: ", sprintf('%.1f%%', 100*cov_rate),
" | Línea vertical = media verdadera"))
abline(v = true_mean, lty = 2)
for (i in 1:R) {
col <- if (coverage[i]) "forestgreen" else "red3"
segments(ICs[i,1], i, ICs[i,2], i, lwd = 2, col = col)
points(means[i], i, pch = 20)
}
invisible(list(df = df, coverage = cov_rate))
}
res_norm_rep <- build_replica_intervals(params$R, params$n, rnorm, params$mu_norm, "Normal_15_5",
mean = params$mu_norm, sd = params$sd_norm)
res_exp_rep <- build_replica_intervals(params$R, params$n, rexp, params$mean_exp, "Exponencial_3_5",
rate = 1/params$mean_exp)
Si se solicita usar Stat:fit para “identificar la distribución de las medias”, la expectativa es que las medias se ajusten a algo cercano a Normal (por CLT). Si no se dispone de ProModel, se pueden reportar nuestros QQ-plots y, opcionalmente, el test de Shapiro-Wilk como evidencia metodológica.
shapiro_norm <- shapiro.test(medias_normal)
shapiro_expo <- shapiro.test(medias_expon)
data.frame(
Distribucion = c("Medias Normal", "Medias Exponencial"),
W = c(unname(shapiro_norm$statistic), unname(shapiro_expo$statistic)),
p_value = c(shapiro_norm$p.value, shapiro_expo$p.value)
)
| Distribucion | W | p_value |
|---|---|---|
| Medias Normal | 0.9316338 | 0.0542709 |
| Medias Exponencial | 0.9364667 | 0.0730857 |
sessionInfo()
## R version 4.5.1 (2025-06-13 ucrt)
## Platform: x86_64-w64-mingw32/x64
## Running under: Windows 11 x64 (build 22631)
##
## Matrix products: default
## LAPACK version 3.12.1
##
## locale:
## [1] LC_COLLATE=Spanish_Colombia.utf8 LC_CTYPE=Spanish_Colombia.utf8
## [3] LC_MONETARY=Spanish_Colombia.utf8 LC_NUMERIC=C
## [5] LC_TIME=Spanish_Colombia.utf8
##
## time zone: America/Bogota
## tzcode source: internal
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## loaded via a namespace (and not attached):
## [1] digest_0.6.37 R6_2.6.1 fastmap_1.2.0 xfun_0.52
## [5] cachem_1.1.0 knitr_1.50 htmltools_0.5.8.1 rmarkdown_2.29
## [9] lifecycle_1.0.4 cli_3.6.5 sass_0.4.10 jquerylib_0.1.4
## [13] compiler_4.5.1 rstudioapi_0.17.1 tools_4.5.1 evaluate_1.0.4
## [17] bslib_0.9.0 yaml_2.3.10 rlang_1.1.6 jsonlite_2.0.0
En esta sección se explica cómo leer e interpretar cada una de las gráficas generadas por el análisis para que puedas comentarlas con precisión en tu entrega.