Este documento es la traducción completa a R del notebook original de Python (
1_Probabilidades.ipynb), conservando la misma teoría, el mismo orden y los mismos ejemplos, pero usando herramientas nativas de R: vectores ysetdiff()/union()/intersect()para conjuntos,MASS::fractions()para fracciones exactas, gráficos con R base yplotrixpara los diagramas de Venn, ysample()/runif()para las simulaciones.
Usamos únicamente paquetes estándar del sistema R: MASS
(para fracciones exactas, equivalente a Fraction de Python)
y plotrix (para dibujar círculos, con lo que construimos
los diagramas de Venn sin depender de un paquete específico de
Venn).
library(MASS) # fractions() -> equivalente a from fractions import Fraction
library(plotrix) # draw.circle() -> para construir los diagramas de Venn
# Paleta de colores (equivalente al diccionario C de Python)
C <- c(azul = "#2980b9", rojo = "#e74c3c", verde = "#27ae60",
naranja = "#e67e22", morado = "#8e44ad", turquesa = "#1abc9c",
gris = "#7f8c8d", oro = "#f1c40f", rosa = "#e91e63")
# Estilo gráfico global (equivalente a plt.rcParams.update({...}))
par(family = "serif", cex = 1, las = 1)## Funciones auxiliares para diagramas de Venn con plotrix (no requieren paquetes de Venn)
venn2_plot <- function(solo_a, solo_b, ambos, label_a, label_b, titulo,
col_a = C["azul"], col_b = C["rojo"]) {
plot(0, 0, type = "n", xlim = c(-1.2, 3.2), ylim = c(-1.5, 1.5),
axes = FALSE, xlab = "", ylab = "", main = titulo)
draw.circle(0, 0, 1.15, col = adjustcolor(col_a, alpha.f = 0.45), border = col_a, lwd = 2)
draw.circle(1.4, 0, 1.15, col = adjustcolor(col_b, alpha.f = 0.45), border = col_b, lwd = 2)
text(-0.55, 0, solo_a, cex = 1.3, font = 2)
text(1.95, 0, solo_b, cex = 1.3, font = 2)
text(0.7, 0, ambos, cex = 1.3, font = 2)
text(-0.15, 1.35, label_a, cex = 1.1, col = col_a, font = 2)
text(1.55, 1.35, label_b, cex = 1.1, col = col_b, font = 2)
}
venn1_plot <- function(valor, label, titulo, col = C["verde"]) {
plot(0, 0, type = "n", xlim = c(-1.5, 1.5), ylim = c(-1.5, 1.5),
axes = FALSE, xlab = "", ylab = "", main = titulo)
draw.circle(0, 0, 1.15, col = adjustcolor(col, alpha.f = 0.4), border = col, lwd = 2)
text(0, 0, valor, cex = 1.3, font = 2)
text(0, 1.35, label, cex = 1.1, col = col, font = 2)
}La probabilidad es una medida numérica de la posibilidad de que ocurra un evento. Toma valores entre 0 (imposible) y 1 (seguro).
Es aquel cuyo resultado no se puede predecir con certeza antes de realizarlo, pero sí se conoce el conjunto de todos los resultados posibles.
| Concepto | Definición | Ejemplo |
|---|---|---|
| Experimento determinista | Resultado predecible | Calentar agua a 100°C → hierve |
| Experimento aleatorio | Resultado incierto | Lanzar un dado → ¿1, 2, 3, 4, 5, 6? |
| Espacio muestral (\(\Omega\)) | Conjunto de todos los resultados posibles | \(\Omega = \{1,2,3,4,5,6\}\) |
| Evento (\(A\)) | Subconjunto de \(\Omega\) | \(A=\{2,4,6\}\) (sale par) |
El espacio muestral \(\Omega\) (o \(S\)) es el conjunto de todos los resultados posibles de un experimento aleatorio.
| Experimento | Espacio muestral |
|---|---|
| Lanzar una moneda | \(\Omega=\{C,S\}\) |
| Lanzar un dado | \(\Omega=\{1,2,3,4,5,6\}\) |
| Lanzar 2 monedas | \(\Omega=\{CC,CS,SC,SS\}\) |
| Lanzar 2 dados | \(|\Omega|=6\times 6=36\) |
En R, representamos conjuntos con vectores (para
elementos simples) o con data frames / listas (para
tuplas, como los pares de dos dados). Las funciones
union(), intersect() y setdiff()
de R base cumplen el mismo papel que |, &
y - sobre set en Python.
# Espacio muestral: lanzar un dado
omega_dado <- 1:6
cat("Omega (dado) =", paste(omega_dado, collapse = ", "), "\n")## Omega (dado) = 1, 2, 3, 4, 5, 6
## |Omega| = 6
# Espacio muestral: lanzar 2 monedas
omega_2monedas <- expand.grid(m1 = c("C", "S"), m2 = c("C", "S"))
omega_2monedas$resultado <- paste0(omega_2monedas$m1, omega_2monedas$m2)
cat("Omega (2 monedas) =", paste(omega_2monedas$resultado, collapse = ", "), "\n")## Omega (2 monedas) = CC, SC, CS, SS
## |Omega| = 4
# Espacio muestral: lanzar 2 dados
omega_2dados <- expand.grid(d1 = 1:6, d2 = 1:6)
cat("|Omega| (2 dados) =", nrow(omega_2dados), "\n")## |Omega| (2 dados) = 36
## Primeros 6:
## d1 d2
## 1 1 1
## 2 2 1
## 3 3 1
## 4 4 1
## 5 5 1
## 6 6 1
## Ultimos 6:
## d1 d2
## 31 1 6
## 32 2 6
## 33 3 6
## 34 4 6
## 35 5 6
## 36 6 6
# Gráfico: espacio muestral de 2 dados
plot(omega_2dados$d1, omega_2dados$d2, pch = 19, cex = 2,
col = adjustcolor(C["azul"], alpha.f = 0.6),
xlim = c(0.5, 6.5), ylim = c(0.5, 7),
xlab = "Dado 1", ylab = "Dado 2",
main = "Espacio Muestral — 2 Dados (36 puntos)", font.main = 2,
xaxt = "n", yaxt = "n")
axis(1, at = 1:6); axis(2, at = 1:6)
text(omega_2dados$d1, omega_2dados$d2 + 0.3,
labels = paste0("(", omega_2dados$d1, ",", omega_2dados$d2, ")"), cex = 0.6)# Árbol: lanzar una moneda 3 veces
plot(0, 0, type = "n", xlim = c(-1, 10), ylim = c(-4, 5), axes = FALSE,
xlab = "", ylab = "", main = "Árbol de Posibilidades — 3 Lanzamientos de Moneda", font.main = 2)
resultados_arbol <- c("C", "S")
for (i in seq_along(resultados_arbol)) {
r1 <- resultados_arbol[i]
y1 <- 3 - (i - 1) * 4
arrows(0, 1, 2, y1, col = C["azul"], lwd = 1.5, length = 0.1)
text(1, (1 + y1) / 2 + 0.3, r1, cex = 1.1, font = 2, col = C["azul"])
for (j in seq_along(resultados_arbol)) {
r2 <- resultados_arbol[j]
y2 <- y1 + 1 - (j - 1) * 2
arrows(2, y1, 5, y2, col = C["verde"], lwd = 1.2, length = 0.08)
text(3.3, (y1 + y2) / 2 + 0.2, r2, cex = 1.0, col = C["verde"])
for (k in seq_along(resultados_arbol)) {
r3 <- resultados_arbol[k]
y3 <- y2 + 0.5 - (k - 1) * 1
arrows(5, y2, 8, y3, col = C["naranja"], lwd = 1, length = 0.06)
text(6.3, (y2 + y3) / 2 + 0.1, r3, cex = 0.9, col = C["naranja"])
text(8.5, y3, paste0(r1, r2, r3), cex = 1.0, font = 2)
}
}
}
text(0, 1, "Inicio", cex = 1.2, font = 2)# Verificación: 2^3 = 8 resultados
omega_3m <- expand.grid(m1 = c("C","S"), m2 = c("C","S"), m3 = c("C","S"))
omega_3m$resultado <- paste0(omega_3m$m1, omega_3m$m2, omega_3m$m3)
cat("Omega =", paste(omega_3m$resultado, collapse = ", "), "\n")## Omega = CCC, SCC, CSC, SSC, CCS, SCS, CSS, SSS
## |Omega| = 8 = 2^3
Un evento es un subconjunto del espacio muestral \(\Omega\).
| Operación | Notación | En R | Significado |
|---|---|---|---|
| Unión | \(A\cup B\) | union(A, B) |
\(A\) o \(B\) (o ambos) |
| Intersección | \(A\cap B\) | intersect(A, B) |
\(A\) y \(B\) |
| Complemento | \(A^c\) o \(\bar A\) | setdiff(Omega, A) |
No \(A\) |
| Diferencia | \(A-B\) | setdiff(A, B) |
\(A\) pero no \(B\) |
| Mutuamente excluyentes | \(A\cap B=\emptyset\) | — | No pueden ocurrir juntos |
# Ejemplo: lanzar un dado
Omega <- 1:6
A <- c(2, 4, 6) # sale par
B <- c(1, 2, 3) # sale <= 3
cat("Omega =", paste(Omega, collapse = ", "), "\n")## Omega = 1, 2, 3, 4, 5, 6
## A (par) = 2, 4, 6
## B (<=3) = 1, 2, 3
## A U B = 2, 4, 6, 1, 3
## A ^ B = 2
## A^c = 1, 3, 5
## A - B = 4, 6
## A ^ B = vacio? FALSE
| Ley | Expresión |
|---|---|
| Conmutativa | \(A\cup B=B\cup A\) |
| Asociativa | \((A\cup B)\cup C=A\cup(B\cup C)\) |
| Distributiva | \(A\cap(B\cup C)=(A\cap B)\cup(A\cap C)\) |
| De Morgan | \((A\cup B)^c=A^c\cap B^c\) |
| De Morgan | \((A\cap B)^c=A^c\cup B^c\) |
# Verificación de las leyes de De Morgan
Ac <- setdiff(Omega, A)
Bc <- setdiff(Omega, B)
# (A U B)^c = A^c ^ B^c
izq <- setdiff(Omega, union(A, B))
der <- intersect(Ac, Bc)
cat("(AUB)^c =", paste(sort(izq), collapse=", "), "\n")## (AUB)^c = 5
## A^c^B^c = 5
## De Morgan 1: TRUE (verificado)
# (A ^ B)^c = A^c U B^c
izq2 <- setdiff(Omega, intersect(A, B))
der2 <- union(Ac, Bc)
cat("\n(A^B)^c =", paste(sort(izq2), collapse=", "), "\n")##
## (A^B)^c = 1, 3, 4, 5, 6
## A^cUB^c = 1, 3, 4, 5, 6
## De Morgan 2: TRUE (verificado)
par(mfrow = c(1, 3), oma = c(0, 0, 3, 0))
n_solo_a <- length(setdiff(A, B))
n_solo_b <- length(setdiff(B, A))
n_ambos <- length(intersect(A, B))
venn2_plot(n_solo_a, n_solo_b, n_ambos, "A (par)", "B (<=3)",
paste0("A \u2229 B = {", paste(intersect(A,B), collapse=","), "}"))
venn2_plot(n_solo_a + n_ambos, n_solo_b + n_ambos, 0, "A", "B", "A \u222a B",
col_a = adjustcolor(C["azul"], alpha.f = 0.3), col_b = adjustcolor(C["rojo"], alpha.f = 0.3))
venn1_plot(length(setdiff(Omega, A)), "A^c",
paste0("A^c = {", paste(setdiff(Omega, A), collapse=","), "}"))
mtext("Diagramas de Venn", side = 3, line = 0.5, outer = TRUE, cex = 1.3, font = 2)\[P(A)=\frac{\text{casos favorables a } A}{\text{casos totales}}=\frac{|A|}{|\Omega|}\]
Requiere que todos los resultados sean igualmente probables.
\[P(A)=\lim_{n\to\infty}\frac{n_A}{n}\]
Donde \(n_A\) es el número de veces que ocurrió \(A\) en \(n\) repeticiones.
| Axioma | Expresión | Descripción |
|---|---|---|
| A1 | \(P(A)\ge 0\) | No negativa |
| A2 | \(P(\Omega)=1\) | Certeza total |
| A3 | Si \(A\cap B=\emptyset\): \(P(A\cup B)=P(A)+P(B)\) | Aditividad |
# Definición Clásica: P(A) = |A| / |Omega|
P_A <- fractions(length(A) / length(Omega))
P_B <- fractions(length(B) / length(Omega))
cat(sprintf("P(par) = |A|/|Omega| = %d/%d = %s = %.4f\n",
length(A), length(Omega), as.character(P_A), length(A)/length(Omega)))## P(par) = |A|/|Omega| = 3/6 = 1/2 = 0.5000
cat(sprintf("P(<=3) = |B|/|Omega| = %d/%d = %s = %.4f\n",
length(B), length(Omega), as.character(P_B), length(B)/length(Omega)))## P(<=3) = |B|/|Omega| = 3/6 = 1/2 = 0.5000
# Probabilidades con fracciones exactas
P_AyB <- fractions(length(intersect(A, B)) / length(Omega))
P_AoB <- fractions(length(union(A, B)) / length(Omega))
P_Ac <- fractions(length(setdiff(Omega, A)) / length(Omega))
cat(sprintf("P(A ^ B) = %d/%d = %s\n", length(intersect(A,B)), length(Omega), as.character(P_AyB)))## P(A ^ B) = 1/6 = 1/6
## P(A U B) = 5/6 = 5/6
## P(A^c) = 3/6 = 1/2
| Propiedad | Fórmula |
|---|---|
| Complemento | \(P(A^c)=1-P(A)\) |
| Evento imposible | \(P(\emptyset)=0\) |
| Rango | \(0\le P(A)\le 1\) |
| Adición general | \(P(A\cup B)=P(A)+P(B)-P(A\cap B)\) |
| Inclusión-exclusión (3) | \(P(A\cup B\cup C)=\sum P-\sum P(\cap\cap)+P(A\cap B\cap C)\) |
# Verificar: P(AUB) = P(A) + P(B) - P(A^B)
izq <- P_AoB
der <- P_A + P_B - P_AyB
cat("P(AUB) =", as.character(izq), "\n")## P(AUB) = 5/6
cat(sprintf("P(A)+P(B)-P(A^B) = %s+%s-%s = %s\n",
as.character(P_A), as.character(P_B), as.character(P_AyB), as.character(der)))## P(A)+P(B)-P(A^B) = 1/2+1/2-1/6 = 5/6
## Iguales? TRUE (verificado)
# Verificar: P(A^c) = 1 - P(A)
cat(sprintf("\nP(A^c) = %s = 1 - %s = %s (verificado)\n",
as.character(P_Ac), as.character(P_A), as.character(fractions(1 - as.numeric(P_A)))))##
## P(A^c) = 1/2 = 1 - 1/2 = 1/2 (verificado)
# Simulación: lanzar un dado N veces
set.seed(42)
N_sim <- 10000
lanzamientos <- sample(1:6, N_sim, replace = TRUE)
# Frecuencia relativa acumulada de "sale par"
es_par <- as.integer(lanzamientos %% 2 == 0)
freq_acum <- cumsum(es_par) / seq_len(N_sim)
cat(sprintf("Frecuencia relativa final (n=%d): %.4f\n", N_sim, tail(freq_acum, 1)))## Frecuencia relativa final (n=10000): 0.4969
## Probabilidad teórica: 0.5000
# Gráfico: convergencia frecuentista
plot(seq_len(N_sim), freq_acum, type = "l", col = C["azul"], lwd = 1,
log = "x", xlab = "Número de lanzamientos (n)", ylab = "Frecuencia relativa n_A / n",
main = "Ley de los Grandes Números — Convergencia Frecuentista", font.main = 2)
abline(h = 0.5, col = C["rojo"], lty = 2, lwd = 2)
legend("topright", legend = "P(par) = 0.5 (teórica)", col = C["rojo"], lty = 2, lwd = 2, bty = "n")Calcular \(P(\text{suma}=7)\) y la distribución completa de la suma.
# Todos los resultados posibles al lanzar 2 dados
resultados <- expand.grid(d1 = 1:6, d2 = 1:6)
sumas <- resultados$d1 + resultados$d2
# P(suma = 7)
fav_7 <- resultados[sumas == 7, ]
P_7 <- fractions(nrow(fav_7) / nrow(resultados))
cat("Casos favorables (suma=7):\n"); print(fav_7)## Casos favorables (suma=7):
## d1 d2
## 6 6 1
## 11 5 2
## 16 4 3
## 21 3 4
## 26 2 5
## 31 1 6
cat(sprintf("P(suma=7) = %d/%d = %s = %.4f\n",
nrow(fav_7), nrow(resultados), as.character(P_7), nrow(fav_7)/nrow(resultados)))## P(suma=7) = 6/36 = 1/6 = 0.1667
# Distribución completa de la suma
df_suma <- data.frame(Suma = 2:12)
df_suma$Casos <- sapply(df_suma$Suma, function(s) sum(sumas == s))
df_suma$P_Suma <- sapply(df_suma$Casos, function(c) as.character(fractions(c / 36)))
df_suma$P_decimal <- df_suma$Casos / 36
df_suma# Gráfico de la distribución de la suma de 2 dados
colores_barras <- ifelse(df_suma$Suma == 7, C["rojo"], C["azul"])
bp <- barplot(df_suma$Casos, names.arg = df_suma$Suma, col = colores_barras, border = "white",
xlab = "Suma de los dados", ylab = "Casos favorables",
main = "Distribución de la Suma de 2 Dados", font.main = 2, ylim = c(0, max(df_suma$Casos)+1))
text(bp, df_suma$Casos + 0.2, labels = paste0(df_suma$Casos, "/36"), font = 2, cex = 0.8)\[P(A|B)=\frac{P(A\cap B)}{P(B)} \qquad \text{con } P(B)>0\]
Se lee: «probabilidad de \(A\) dado que \(B\) ya ocurrió».
\[P(A\cap B)=P(A|B)\cdot P(B)=P(B|A)\cdot P(A)\]
\(A\) y \(B\) son independientes si y solo si:
\[P(A\cap B)=P(A)\cdot P(B)\]
Equivalentemente: \(P(A|B)=P(A)\) (saber que \(B\) ocurrió no cambia la probabilidad de \(A\)).
# P(par | suma <= 6) = P(par ^ suma<=6) / P(suma<=6)
A_par <- which(resultados$d1 %% 2 == 0) # dado 1 par (índices de filas)
B_suma6 <- which(resultados$d1 + resultados$d2 <= 6) # suma <= 6
AyB <- intersect(A_par, B_suma6)
P_AyB <- fractions(length(AyB) / 36)
P_B_s6 <- fractions(length(B_suma6) / 36)
P_cond <- fractions(as.numeric(P_AyB) / as.numeric(P_B_s6))
cat("A (dado1 par): |A| =", length(A_par), "\n")## A (dado1 par): |A| = 18
## B (suma <= 6): |B| = 15
## A ^ B: |A^B| = 6
##
## P(A^B) = 1/6
## P(B) = 5/12
cat(sprintf("P(A|B) = %s/%s = %s ~= %.4f\n",
as.character(P_AyB), as.character(P_B_s6), as.character(P_cond),
as.numeric(P_AyB)/as.numeric(P_B_s6)))## P(A|B) = 1/6/5/12 = 2/5 ~= 0.4000
Una urna contiene 5 bolas rojas y 3 bolas azules. Se extraen 2 bolas sin reposición.
## === Extracción SIN reposición ===
P_1roja <- fractions(5/8)
P_2azul_dado_1roja <- fractions(3/7)
P_ambas <- fractions(as.numeric(P_1roja) * as.numeric(P_2azul_dado_1roja))
cat("P(1a roja) =", as.character(P_1roja), "\n")## P(1a roja) = 5/8
## P(2a azul | 1a roja) = 3/7
cat(sprintf("P(1a roja ^ 2a azul) = %s x %s = %s\n",
as.character(P_1roja), as.character(P_2azul_dado_1roja), as.character(P_ambas)))## P(1a roja ^ 2a azul) = 5/8 x 3/7 = 15/56
## ~= 0.2679
##
## === Extracción CON reposición ===
P_2azul_con_rep <- fractions(3/8) # no cambia
P_ambas_con_rep <- fractions(as.numeric(P_1roja) * as.numeric(P_2azul_con_rep))
cat(sprintf("P(1a roja) x P(2a azul) = %s x %s = %s\n",
as.character(P_1roja), as.character(P_2azul_con_rep), as.character(P_ambas_con_rep)))## P(1a roja) x P(2a azul) = 5/8 x 3/8 = 15/64
## CON reposición -> eventos INDEPENDIENTES
## SIN reposición -> eventos DEPENDIENTES
# ¿Son independientes A={par} y B={<=3} al lanzar un dado?
P_A_d <- fractions(3/6) # {2,4,6}
P_B_d <- fractions(3/6) # {1,2,3}
P_AyB_d <- fractions(1/6) # {2}
P_prod <- fractions(as.numeric(P_A_d) * as.numeric(P_B_d))
cat("P(A) =", as.character(P_A_d), "\n")## P(A) = 1/2
## P(B) = 1/2
## P(A) x P(B) = 1/4
## P(A ^ B) = 1/6
##
## ¿Independientes? P(A^B) = P(A)xP(B)?
## 1/6 != 1/4 -> NO son independientes
Los eventos \(B_1,B_2,\dots,B_n\) forman una partición de \(\Omega\) si:
\[P(A)=\sum_{i=1}^n P(A|B_i)\cdot P(B_i)\]
\[P(B_k|A)=\frac{P(A|B_k)\cdot P(B_k)}{\sum_{i=1}^n P(A|B_i)\cdot P(B_i)}=\frac{P(A|B_k)\cdot P(B_k)}{P(A)}\]
Una fábrica tiene 3 máquinas:
| Máquina | % de producción | % de defectos |
|---|---|---|
| M1 | 50% | 3% |
| M2 | 30% | 4% |
| M3 | 20% | 5% |
a) ¿Cuál es la probabilidad de que un producto al azar sea defectuoso? b) Si un producto resultó defectuoso, ¿de qué máquina es más probable que provenga?
# Datos
maquinas <- c("M1", "M2", "M3")
P_M <- c(0.50, 0.30, 0.20) # P(Bi)
P_D_dado_M <- c(0.03, 0.04, 0.05) # P(A|Bi)# a) Probabilidad Total: P(D) = Sum P(D|Mi) * P(Mi)
P_D <- sum(P_D_dado_M * P_M)
cat("=== Probabilidad Total ===\n")## === Probabilidad Total ===
for (i in seq_along(maquinas)) {
cat(sprintf(" P(D|%s)*P(%s) = %.2f x %.2f = %.4f\n",
maquinas[i], maquinas[i], P_D_dado_M[i], P_M[i], P_D_dado_M[i]*P_M[i]))
}## P(D|M1)*P(M1) = 0.03 x 0.50 = 0.0150
## P(D|M2)*P(M2) = 0.04 x 0.30 = 0.0120
## P(D|M3)*P(M3) = 0.05 x 0.20 = 0.0100
##
## P(D) = 0.0370 = 3.70%
# b) Bayes: P(Mi|D) = P(D|Mi)*P(Mi) / P(D)
P_M_dado_D <- (P_D_dado_M * P_M) / P_D
cat("=== Teorema de Bayes ===\n")## === Teorema de Bayes ===
for (i in seq_along(maquinas)) {
cat(sprintf(" P(%s|D) = %.4f = %.2f%%\n", maquinas[i], P_M_dado_D[i], P_M_dado_D[i]*100))
}## P(M1|D) = 0.4054 = 40.54%
## P(M2|D) = 0.3243 = 32.43%
## P(M3|D) = 0.2703 = 27.03%
cat(sprintf("\n-> La máquina más probable es %s con P = %.2f%%\n",
maquinas[which.max(P_M_dado_D)], max(P_M_dado_D)*100))##
## -> La máquina más probable es M1 con P = 40.54%
## Verificación: Sum P(Mi|D) = 1.0000 (correcto)
# Gráfico: probabilidad a priori vs a posteriori
par(mfrow = c(1, 2), oma = c(0, 0, 3, 0))
colores_maq <- c(C["azul"], C["verde"], C["naranja"])
bp1 <- barplot(P_M*100, names.arg = maquinas, col = colores_maq, border = "white",
ylab = "Probabilidad (%)", main = "A Priori: P(Mi)", font.main = 2, ylim = c(0, 65))
text(bp1, P_M*100 + 1.5, labels = paste0(round(P_M*100), "%"), font = 2)
bp2 <- barplot(P_M_dado_D*100, names.arg = maquinas, col = colores_maq, border = "white",
ylab = "Probabilidad (%)", main = "A Posteriori: P(Mi|D) — Bayes", font.main = 2, ylim = c(0, 55))
text(bp2, P_M_dado_D*100 + 1.5, labels = paste0(round(P_M_dado_D*100, 1), "%"), font = 2)
mtext("Bayes: Actualización de Probabilidades", side = 3, line = 0.5, outer = TRUE, cex = 1.3, font = 2)Una enfermedad afecta al 1% de la población. Un test tiene:
Si una persona da positivo, ¿cuál es la probabilidad de que realmente esté enferma?
# Datos del test médico
P_E <- 0.01 # Prevalencia
P_noE <- 1 - P_E # P(sano)
P_pos_dado_E <- 0.95 # Sensibilidad
P_neg_dado_noE <- 0.90 # Especificidad
P_pos_dado_noE <- 1 - P_neg_dado_noE # Falso positivo
# P(+) = P(+|E)*P(E) + P(+|E^c)*P(E^c)
P_pos <- P_pos_dado_E * P_E + P_pos_dado_noE * P_noE
# P(E|+) = P(+|E)*P(E) / P(+)
P_E_dado_pos <- (P_pos_dado_E * P_E) / P_pos
cat(sprintf("P(+) = %.4f\n", P_pos))## P(+) = 0.1085
## P(E|+) = 0.0876 = 8.76%
##
## -> ¡Solo el 8.8% de los positivos están realmente enfermos!
## Esto se debe a la baja prevalencia (1%) y los falsos positivos.
# Visualización: composición de los positivos
verdaderos_pos <- P_pos_dado_E * P_E
falsos_pos <- P_pos_dado_noE * P_noE
bp <- barplot(c(verdaderos_pos, falsos_pos),
names.arg = c("Verdaderos\nPositivos", "Falsos\nPositivos"),
col = c(C["verde"], C["rojo"]), border = "white",
ylab = "Proporción", main = "Composición de los Tests Positivos", font.main = 2,
ylim = c(0, max(verdaderos_pos, falsos_pos)*1.3))
text(bp[1], verdaderos_pos + 0.003,
labels = sprintf("%.4f\n(%.1f%%)", verdaderos_pos, verdaderos_pos/P_pos*100), font = 2)
text(bp[2], falsos_pos + 0.003,
labels = sprintf("%.4f\n(%.1f%%)", falsos_pos, falsos_pos/P_pos*100), font = 2)Verificamos todas las probabilidades teóricas mediante simulación.
# Simulación: lanzar 2 dados 100 000 veces
set.seed(0)
N_mc <- 100000
d1 <- sample(1:6, N_mc, replace = TRUE)
d2 <- sample(1:6, N_mc, replace = TRUE)
suma_mc <- d1 + d2# Comparar P teórica vs simulada
cat(sprintf("%6s | %10s | %10s | %8s\n", "Suma", "P teorica", "P simulada", "Error"))## Suma | P teorica | P simulada | Error
## —————————————————————————————————————————————
for (s in 2:12) {
p_teo <- sum(sumas == s) / 36
p_sim <- sum(suma_mc == s) / N_mc
error <- abs(p_teo - p_sim)
cat(sprintf("%6d | %10.4f | %10.4f | %8.4f\n", s, p_teo, p_sim, error))
}## 2 | 0.0278 | 0.0278 | 0.0000
## 3 | 0.0556 | 0.0545 | 0.0011
## 4 | 0.0833 | 0.0823 | 0.0011
## 5 | 0.1111 | 0.1112 | 0.0001
## 6 | 0.1389 | 0.1401 | 0.0012
## 7 | 0.1667 | 0.1677 | 0.0010
## 8 | 0.1389 | 0.1385 | 0.0004
## 9 | 0.1111 | 0.1103 | 0.0008
## 10 | 0.0833 | 0.0846 | 0.0013
## 11 | 0.0556 | 0.0553 | 0.0003
## 12 | 0.0278 | 0.0278 | 0.0000
# Gráfico: teórica vs simulada
teoricas <- sapply(2:12, function(s) sum(sumas == s) / 36)
simuladas <- sapply(2:12, function(s) sum(suma_mc == s) / N_mc)
x <- 2:12
w <- 0.35
plot(0, 0, type = "n", xlim = c(1.3, 12.7), ylim = c(0, max(teoricas, simuladas) * 1.2),
xlab = "Suma", ylab = "Probabilidad", main = "P(Suma) — Teórica vs Monte Carlo",
font.main = 2, xaxt = "n")
axis(1, at = x)
rect(x - w, 0, x, teoricas, col = C["azul"], border = "white")
rect(x, 0, x + w, simuladas, col = C["naranja"], border = "white")
legend("topright", legend = c("Teórica", paste0("Simulada (n=", format(N_mc, big.mark=","), ")")),
fill = c(C["azul"], C["naranja"]), bty = "n")tabla_resumen <- data.frame(
Concepto = c("Espacio muestral", "Unión", "Intersección", "Complemento",
"P. Clásica (Laplace)", "P. Condicional", "Regla multiplicación",
"Independencia", "Prob. Total", "Bayes", "Simulación", "Fracciones exactas"),
Formula = c("Omega = {todos los resultados}", "A U B", "A ^ B", "A^c = Omega - A",
"P(A) = |A| / |Omega|", "P(A|B) = P(A^B) / P(B)", "P(A^B) = P(A|B)*P(B)",
"P(A^B) = P(A)*P(B)", "P(A) = Sum P(A|Bi)*P(Bi)", "P(Bk|A) = P(A|Bk)*P(Bk)/P(A)",
"Frecuencia relativa -> P", "—"),
R = c("1:6, expand.grid()", "union(A, B)", "intersect(A, B)", "setdiff(Omega, A)",
"length(A) / length(Omega)", "P_AyB / P_B", "P_A_dado_B * P_B",
"P_A * P_B", "sum(P_A_dado_B * P_B)", "(P_A_Bk * P_Bk) / P_A",
"sample(1:6, N, replace=TRUE)", "MASS::fractions(a/b)")
)
knitr::kable(tabla_resumen, align = "l",
caption = "Tabla resumen: concepto, fórmula y su equivalente en R")| Concepto | Formula | R |
|---|---|---|
| Espacio muestral | Omega = {todos los resultados} | 1:6, expand.grid() |
| Unión | A U B | union(A, B) |
| Intersección | A ^ B | intersect(A, B) |
| Complemento | A^c = Omega - A | setdiff(Omega, A) |
| P. Clásica (Laplace) | P(A) = |A| / |Omega| | length(A) / length(Omega) |
| P. Condicional | P(A|B) = P(A^B) / P(B) | P_AyB / P_B |
| Regla multiplicación | P(A^B) = P(A|B)*P(B) | P_A_dado_B * P_B |
| Independencia | P(A^B) = P(A)*P(B) | P_A * P_B |
| Prob. Total | P(A) = Sum P(A|Bi)*P(Bi) | sum(P_A_dado_B * P_B) |
| Bayes | P(Bk|A) = P(A|Bk)*P(Bk)/P(A) | (P_A_Bk * P_Bk) / P_A |
| Simulación | Frecuencia relativa -> P | sample(1:6, N, replace=TRUE) |
| Fracciones exactas | — | MASS::fractions(a/b) |
Se lanzan 3 dados simultáneamente.
En una clase de 40 estudiantes: 25 aprueban Matemáticas (\(M\)), 20 aprueban Estadística (\(E\)) y 15 aprueban ambas.
venn2_plot() / venn1_plot() definidas al
inicio de este documento (o el paquete de su preferencia).En una baraja de 52 cartas se extraen 2 cartas sin reposición.
sample()) y compare con
las teóricas.Se lanza un dado y una moneda simultáneamente.
Un laboratorio tiene 2 técnicos. El técnico A procesa el 60% de las muestras con 2% de error; el técnico B procesa el 40% con 5% de error.
En un concurso hay 3 puertas: detrás de una hay un auto y detrás de las otras 2 hay cabras. Eliges una puerta, el presentador abre otra (que tiene cabra) y te ofrece cambiar.
Este cuaderno cubre Probabilidades con:
plotrixMASS::fractions)
Documento elaborado por MSc. Jeel Cueva — Especialista
en Econometría Aplicada.
Traducción a R Markdown del notebook
original de Python, publicable en RPubs.