En la gestión de la cadena de suministro y el control de calidad, a menudo nos enfrentamos a la incertidumbre sobre el origen de un lote de productos defectuosos. La Actualización Secuencial Bayesiana es una técnica robusta que permite refinar nuestras estimaciones iniciales (probabilidades a priori) conforme se inspeccionan múltiples unidades de forma sucesiva.
A diferencia de un análisis estático, el enfoque secuencial utiliza la probabilidad posterior obtenida tras una observación como la probabilidad prior para la siguiente inspección. Este proceso de retroalimentación permite identificar con mayor precisión cuál es el proveedor más probable basándose en la evidencia acumulada (piezas defectuosas o conformes), optimizando así la toma de decisiones en el departamento de calidad de instituciones o empresas.
A continuación, se detalla el código que automatiza el cálculo de la tabla bayesiana y realiza tres actualizaciones consecutivas basadas en hallazgos reales.
# ==============================================================================
# BAYES — Caso 2: Control de Calidad + Actualización Secuencial
# Objetivo: Determinar qué proveedor nos envió un lote basándonos en piezas
# defectuosas encontradas sucesivamente.
# ==============================================================================
# ------------------------------------------------------------------------------
# 1. DEFINICIÓN DE LA FUNCIÓN MOTOR
# Esta función automatiza el cálculo de la probabilidad posterior para N estados.
# ------------------------------------------------------------------------------
bayes_tabla <- function(prior, likel, estados) {
# Paso A: Cálculo de Probabilidad Conjunta (Intersección)
# Multiplicamos lo que creíamos (Prior) por qué tan común es el evento (Likel).
conjunta <- prior * likel
# Paso B: Probabilidad Total de la Evidencia (P_E)
# Es la suma de todas las conjuntas. Sirve para normalizar los datos.
P_E <- sum(conjunta)
# Paso C: Cálculo de la Posterior (Actualización)
# Aplicamos el Teorema de Bayes: P(H|E) = P(H∩E) / P(E)
posterior <- conjunta / P_E
# Paso D: Creación de un informe tabular para análisis visual
df <- data.frame(
Estado = estados,
Prior = round(prior, 4), # Creencia antes de ver la pieza
Likel = round(likel, 4), # Probabilidad de observar el defecto/conforme
Conjunta = round(conjunta, 4), # Peso relativo de la hipótesis
P_E = round(P_E, 4), # Probabilidad marginal total
Posterior = round(posterior, 4) # Nueva creencia después de la pieza
)
# Devolvemos la tabla y el vector de posteriors para usarlo en la siguiente iteración
list(tabla = df, posterior = posterior, P_E = P_E)
}
# ------------------------------------------------------------------------------
# 2. CONFIGURACIÓN DE DATOS INICIALES
# ------------------------------------------------------------------------------
# Identificamos a los sujetos de estudio (nuestros proveedores)
estados <- c("Proveedor A", "Proveedor B", "Proveedor C")
# Prior Inicial: Basado en registros de compra (A provee el 60%, B el 30%, C el 10%)
prior <- c(0.60, 0.30, 0.10)
# Verosimilitudes (Tasas históricas de error/acierto por cada proveedor)
p_defecto <- c(0.01, 0.04, 0.12) # P(Defecto | Proveedor) -> El C es el más descuidado
p_conforme <- c(0.99, 0.96, 0.88) # P(Conforme | Proveedor) -> El A es el más confiable
# ------------------------------------------------------------------------------
# 3. EJECUCIÓN SECUENCIAL (APRENDIZAJE AUTOMÁTICO)
# ------------------------------------------------------------------------------
# --- INSPECCIÓN 1: Se extrae una pieza y sale DEFECTUOSA ---
# Sirve para: Empezar a dudar de los proveedores con mayor tasa de error.
cat("=== INSPECCIÓN 1: DEFECTUOSA ===\n")
## === INSPECCIÓN 1: DEFECTUOSA ===
res1 <- bayes_tabla(prior, p_defecto, estados)
print(res1$tabla[, c("Estado","Prior","Likel","Conjunta","Posterior")])
## Estado Prior Likel Conjunta Posterior
## 1 Proveedor A 0.6 0.01 0.006 0.2
## 2 Proveedor B 0.3 0.04 0.012 0.4
## 3 Proveedor C 0.1 0.12 0.012 0.4
# --- INSPECCIÓN 2: Segunda pieza DEFECTUOSA ---
# Propósito: La posterior del paso 1 se convierte en el prior de este paso.
# Sirve para: Reforzar la evidencia. Si sale otra falla, la culpa se inclina hacia C.
cat("\n=== INSPECCIÓN 2: DEFECTUOSA (prior actualizado) ===\n")
##
## === INSPECCIÓN 2: DEFECTUOSA (prior actualizado) ===
res2 <- bayes_tabla(res1$posterior, p_defecto, estados)
print(res2$tabla[, c("Estado","Prior","Likel","Posterior")])
## Estado Prior Likel Posterior
## 1 Proveedor A 0.2 0.01 0.0303
## 2 Proveedor B 0.4 0.04 0.2424
## 3 Proveedor C 0.4 0.12 0.7273
# --- INSPECCIÓN 3: Tercera pieza sale CONFORME (Sin fallas) ---
# Propósito: Evaluar cómo una buena noticia limpia la imagen de los proveedores.
# Sirve para: Ver que el modelo no solo castiga, sino que ajusta según la realidad.
cat("\n=== INSPECCIÓN 3: CONFORME ===\n")
##
## === INSPECCIÓN 3: CONFORME ===
res3 <- bayes_tabla(res2$posterior, p_conforme, estados)
print(res3$tabla[, c("Estado","Prior","Likel","Posterior")])
## Estado Prior Likel Posterior
## 1 Proveedor A 0.0303 0.99 0.0332
## 2 Proveedor B 0.2424 0.96 0.2578
## 3 Proveedor C 0.7273 0.88 0.7090
# ------------------------------------------------------------------------------
# 4. VISUALIZACIÓN DE LA EVOLUCIÓN
# ------------------------------------------------------------------------------
library(ggplot2) # Para graficar
library(tidyr) # Para reestructurar los datos
# Creamos una matriz de seguimiento para ver cómo cambió la probabilidad en cada paso
evolución <- data.frame(
Inspección = c("Prior", "Tras Def1", "Tras Def2", "Tras Conf"),
A = c(prior[1], res1$posterior[1], res2$posterior[1], res3$posterior[1]),
B = c(prior[2], res1$posterior[2], res2$posterior[2], res3$posterior[2]),
C = c(prior[3], res1$posterior[3], res2$posterior[3], res3$posterior[3])
)
# Transformamos los datos a formato "largo" para que ggplot pueda interpretarlos por color
df_long <- pivot_longer(evolución, -Inspección,
names_to = "Proveedor", values_to = "Probabilidad")
# Ordenamos las etiquetas del eje X para que sigan el orden cronológico
df_long$Inspección <- factor(df_long$Inspección,
levels = c("Prior","Tras Def1","Tras Def2","Tras Conf"))
# Generamos el gráfico de trayectoria
ggplot(df_long, aes(x = Inspección, y = Probabilidad,
color = Proveedor, group = Proveedor)) +
geom_line(linewidth = 1.2) + # Línea de evolución
geom_point(size = 3.5) + # Puntos en cada inspección
geom_label(aes(label = paste0(round(Probabilidad * 100, 1), "%")),
size = 3, show.legend = FALSE, vjust = -0.5) + # Etiquetas de porcentaje
scale_color_manual(values = c(A="#3a7fbd", B="#d97706", C="#b0305a")) + # Colores personalizados
scale_y_continuous(labels = function(x) paste0(round(x*100,0),"%"), limits=c(0,1)) +
labs(title = "Actualización Secuencial Bayesiana — Control de Calidad",
subtitle = "Cómo cambia nuestra creencia sobre el origen del lote tras cada inspección",
y = "Probabilidad Posterior de que sea el Proveedor X",
x = "Etapa del Proceso") +
theme_minimal() # Tema visual limpio
Conclusiones Estadísticas
Sensibilidad ante la Evidencia: Aunque el Proveedor A era el más probable inicialmente (60%), tras encontrar solo dos piezas defectuosas, su probabilidad cayó drásticamente. Esto demuestra que la evidencia de falla tiene un peso estadístico muy fuerte contra proveedores de “alta calidad”.
Identificación de Anomalías: El Proveedor C, que solo representaba el 10% de las compras, se convirtió en el principal sospechoso (más del 50% de probabilidad) tras el segundo defecto, debido a que su tasa de error (12%) es mucho más alta que las demás.
Efecto de la Pieza Conforme: La tercera inspección (pieza conforme) estabilizó el modelo, devolviéndole algo de crédito al Proveedor B. Esto ilustra que el Teorema de Bayes es “justo”: así como castiga las fallas, también incorpora los éxitos para ajustar la realidad.