Analytical
  • Home
  • Cursos
  • Charlas
  • Blog
  • Libro
  • Sobre mí
  1. Métodos Estadísticos Modernos aplicados en Química Analítica
  2. Bootstrap
  • Métodos Estadísticos Modernos aplicados en Química Analítica
    • Instalación de R
    • Introducción a R
    • Calibración
    • Comparación de métodos analíticos
    • ANOVA
    • Bootstrap
    • Análisis de datos no normales
    • Test de Permutaciones
    • Métodos Robustos
    • Método de Monte Carlo
    • Incertidumbre
    • Reportes y presentaciones
    • Referencias

En esta página

  • ¿Qué es el método Bootstrap?
  • ¿Cómo funciona?
  • Ventajas del Bootstrap
  • Desventajas del Bootstrap
  • ¿Cuándo no usar Bootstrap?
  • Implementación en R
    • Paquetes Necesarios
  • Ejemplo 1: Análisis de Concentración de Cobre en Muestras de Agua
    • Generación de Datos Simulados
    • Bootstrap de la Media
    • Visualización de Resultados
  • Ejemplo 2: Curva de Calibración con Incertidumbre Bootstrap
    • Datos de Calibración
    • Bootstrap de Parámetros de Regresión
    • Visualización de la Curva de Calibración
  • Ejemplo 3: Límite de Detección con Bootstrap
    • Análisis de Blancos
    • Visualización del LOD
  • Ejemplo 4: Comparación de Métodos Analíticos
    • Datos de Comparación
    • Visualización de Comparación
  1. Métodos Estadísticos Modernos aplicados en Química Analítica
  2. Bootstrap

Bootstrap

Fecha de publicación

6 de agosto de 2025

¿Qué es el método Bootstrap?

El método Bootstrap es una técnica de remuestreo desarrollada por Bradley Efron en 1979. Su idea central es simple pero poderosa: si tenemos una muestra de datos, podemos generar muchas “nuevas muestras” extrayendo con reemplazo de la original. A partir de estas muestras, calculamos el estadístico de interés (media, mediana, pendiente, etc.) y obtenemos su distribución empírica Davison y Hinkley (1997).

En Química Analítica, donde los tamaños muestrales suelen ser pequeños y los supuestos clásicos (como normalidad) no siempre se cumplen, el Bootstrap se convierte en una herramienta muy útil para estimar incertidumbres(González y Herrador 2010)

¿Cómo funciona?

  1. Se parte de una muestra original de tamaño ( n ).
  2. Se generan ( R ) muestras bootstrap, cada una de tamaño ( n ), extrayendo con reemplazo.
  3. Se calcula el estadístico de interés en cada muestra.
  4. Se obtiene la distribución empírica del estadístico.
  5. Se estiman intervalos de confianza, sesgo, varianza, etc.

Ventajas del Bootstrap

  • No requiere supuestos de distribución: Ideal cuando no se puede asumir normalidad.
  • Flexible: Se puede aplicar a medias, medianas, pendientes, coeficientes de regresión, etc.
  • Intuitivo: Fácil de explicar y visualizar.
  • Compatible con software moderno: En R, basta una línea de código para implementarlo.

Desventajas del Bootstrap

  • Dependencia de la muestra original: Si la muestra es muy pequeña o no representativa, el Bootstrap puede amplificar sesgos.
  • No siempre funciona bien con extremos: Por ejemplo, estimar percentiles muy altos o bajos puede ser problemático.
  • Computacionalmente intensivo: Aunque hoy en día esto no es un gran problema.

¿Cuándo no usar Bootstrap?

  • Cuando la muestra es demasiado pequeña (por ejemplo, menos de 5 datos), el remuestreo puede generar resultados poco confiables.
  • Cuando el estadístico de interés es no continuo o tiene una distribución muy sesgada.
  • Cuando se dispone de un modelo teórico bien validado y se cumplen sus supuestos (por ejemplo, regresión lineal con errores normales y homocedásticos).

Implementación en R

Paquetes Necesarios

# Cargar librerías necesarias
library(simpleboot)
library(ggplot2)
library(dplyr)
library(boot)
library(tidyr)

# Configurar tema para gráficos
theme_set(theme_minimal())

Ejemplo 1: Análisis de Concentración de Cobre en Muestras de Agua

Generación de Datos Simulados

# Datos simulados de concentración de Cu en mg/L
set.seed(123)
concentraciones_cu <- c(2.45, 2.52, 2.38, 2.41, 2.49, 2.44, 2.47, 2.43, 2.50, 2.46)

# Estadísticas básicas
summary(concentraciones_cu)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  2.380   2.433   2.455   2.455   2.485   2.520 

Bootstrap de la Media

# Bootstrap de la media usando simpleboot
bootstrap_media <- one.boot(concentraciones_cu, mean, R = 10000)


# Intervalo de confianza 95%
ic_media <- boot.ci(bootstrap_media, type = "perc", conf = 0.95)
print(ic_media)
BOOTSTRAP CONFIDENCE INTERVAL CALCULATIONS
Based on 10000 bootstrap replicates

CALL : 
boot.ci(boot.out = bootstrap_media, conf = 0.95, type = "perc")

Intervals : 
Level     Percentile     
95%   ( 2.43,  2.48 )  
Calculations and Intervals on Original Scale

Visualización de Resultados

# Crear dataframe para ggplot2
bootstrap_df <- data.frame(
  media_bootstrap = bootstrap_media$t
)

# Histograma de la distribución bootstrap
p1 <- ggplot(bootstrap_df, aes(x = media_bootstrap)) +
  geom_histogram(bins = 50, fill = "lightblue", color = "black", alpha = 0.7) +
  geom_vline(aes(xintercept = mean(concentraciones_cu)), 
             color = "red", linetype = "dashed", size = 1) +
  labs(title = "Distribución Bootstrap de la Media",
       subtitle = "Concentración de Cu en agua (mg/L)",
       x = "Media Bootstrap (mg/L)",
       y = "Frecuencia") +
  theme_minimal()

# Q-Q plot para evaluar normalidad
p2 <- ggplot(bootstrap_df, aes(sample = media_bootstrap)) +
  stat_qq() +
  stat_qq_line(color = "red") +
  labs(title = "Q-Q Plot - Distribución Bootstrap",
       x = "Cuantiles Teóricos",
       y = "Cuantiles Bootstrap") +
  theme_minimal()

# Mostrar gráficos lado a lado
gridExtra::grid.arrange(p1, p2, ncol = 2)

Ejemplo 2: Curva de Calibración con Incertidumbre Bootstrap

Datos de Calibración

# Datos de calibración para espectrofotometría UV-Vis
concentraciones_std <- c(0, 5, 10, 15, 20, 25, 30)
absorbancias <- c(0.002, 0.125, 0.248, 0.371, 0.496, 0.618, 0.741)

# Agregar ruido experimental realista
set.seed(456)
absorbancias <- absorbancias + rnorm(length(absorbancias), 0, 0.005)

# Crear dataframe
calibracion_data <- data.frame(
  concentracion = concentraciones_std,
  absorbancia = absorbancias
)

print(calibracion_data)
  concentracion  absorbancia
1             0 -0.004717607
2             5  0.128108878
3            10  0.252004373
4            15  0.364055538
5            20  0.492428216
6            25  0.616379695
7            30  0.744453215

Bootstrap de Parámetros de Regresión

# Función para obtener coeficientes de regresión lineal
coef_regression <- function(data, indices) {
  sample_data <- data[indices, ]
  model <- lm(absorbancia ~ concentracion, data = sample_data)
  return(c(model$coefficients[1], model$coefficients[2], summary(model)$r.squared))
}

# Bootstrap de los coeficientes
bootstrap_coef <- boot(data = calibracion_data, 
                       statistic = coef_regression, 
                       R = 5000)

# Intervalos de confianza para intercepto, pendiente y R²
ic_intercepto <- boot.ci(bootstrap_coef, type = "perc", conf = 0.95, index = 1)
ic_pendiente <- boot.ci(bootstrap_coef, type = "perc", conf = 0.95, index = 2)
ic_r2 <- boot.ci(bootstrap_coef, type = "perc", conf = 0.95, index = 3)

print("Intervalo de confianza - Intercepto:")
[1] "Intervalo de confianza - Intercepto:"
print(ic_intercepto)
BOOTSTRAP CONFIDENCE INTERVAL CALCULATIONS
Based on 5000 bootstrap replicates

CALL : 
boot.ci(boot.out = bootstrap_coef, conf = 0.95, type = "perc", 
    index = 1)

Intervals : 
Level     Percentile     
95%   (-0.0081,  0.0071 )  
Calculations and Intervals on Original Scale
print("Intervalo de confianza - Pendiente:")
[1] "Intervalo de confianza - Pendiente:"
print(ic_pendiente)
BOOTSTRAP CONFIDENCE INTERVAL CALCULATIONS
Based on 5000 bootstrap replicates

CALL : 
boot.ci(boot.out = bootstrap_coef, conf = 0.95, type = "perc", 
    index = 2)

Intervals : 
Level     Percentile     
95%   ( 0.0243,  0.0250 )  
Calculations and Intervals on Original Scale
print("Intervalo de confianza - R²:")
[1] "Intervalo de confianza - R²:"
print(ic_r2)
BOOTSTRAP CONFIDENCE INTERVAL CALCULATIONS
Based on 5000 bootstrap replicates

CALL : 
boot.ci(boot.out = bootstrap_coef, conf = 0.95, type = "perc", 
    index = 3)

Intervals : 
Level     Percentile     
95%   ( 0.999,  1.000 )  
Calculations and Intervals on Original Scale

Visualización de la Curva de Calibración

# Modelo original
modelo_original <- lm(absorbancia ~ concentracion, data = calibracion_data)

# Crear dataframe con resultados bootstrap
bootstrap_params <- data.frame(
  intercepto = bootstrap_coef$t[, 1],
  pendiente = bootstrap_coef$t[, 2],
  r_squared = bootstrap_coef$t[, 3]
)

# Gráfico de la curva de calibración con bandas de confianza
p3 <- ggplot(calibracion_data, aes(x = concentracion, y = absorbancia)) +
  geom_point(size = 3, color = "blue") +
  geom_smooth(method = "lm", se = TRUE, color = "red", alpha = 0.3) +
  labs(title = "Curva de Calibración con Intervalos de Confianza",
       subtitle = "Espectrofotometría UV-Vis",
       x = "Concentración (mg/L)",
       y = "Absorbancia") +
  theme_minimal() +
  theme(plot.title = element_text(hjust = 0.5),
        plot.subtitle = element_text(hjust = 0.5))

# Distribución de parámetros bootstrap
p4 <- bootstrap_params %>%
  pivot_longer(everything(), names_to = "parametro", values_to = "valor") %>%
  ggplot(aes(x = valor)) +
  geom_histogram(bins = 30, fill = "lightgreen", alpha = 0.7) +
  facet_wrap(~parametro, scales = "free", ncol = 1,
             labeller = as_labeller(c(intercepto = "Intercepto", 
                                    pendiente = "Pendiente", 
                                    r_squared = "R²"))) +
  labs(title = "Distribución Bootstrap de Parámetros de Regresión",
       x = "Valor del Parámetro",
       y = "Frecuencia") +
  theme_minimal()

# Mostrar gráficos
print(p3)

print(p4)

Ejemplo 3: Límite de Detección con Bootstrap

Análisis de Blancos

# Datos de mediciones de blancos (señal de fondo)
set.seed(789)
blancos <- rnorm(20, mean = 0.005, sd = 0.002)

# Bootstrap para estimar la desviación estándar de los blancos
bootstrap_sd_blancos <- one.boot(blancos, sd, R = 10000)

# Límite de detección (LOD = 3 * SD_blancos)
lod_bootstrap <- 3 * bootstrap_sd_blancos$t

# Estadísticas del LOD
lod_stats <- data.frame(
  LOD_bootstrap = lod_bootstrap
)

summary(lod_stats)
 LOD_bootstrap     
 Min.   :0.001844  
 1st Qu.:0.003533  
 Median :0.004168  
 Mean   :0.004160  
 3rd Qu.:0.004729  
 Max.   :0.007037  

Visualización del LOD

p5 <- ggplot(lod_stats, aes(x = LOD_bootstrap)) +
  geom_histogram(bins = 50, fill = "orange", alpha = 0.7) +
  geom_vline(aes(xintercept = mean(LOD_bootstrap)), 
             color = "red", linetype = "dashed", size = 1) +
  geom_vline(aes(xintercept = quantile(LOD_bootstrap, 0.025)), 
             color = "blue", linetype = "dotted") +
  geom_vline(aes(xintercept = quantile(LOD_bootstrap, 0.975)), 
             color = "blue", linetype = "dotted") +
  labs(title = "Distribución Bootstrap del Límite de Detección",
       subtitle = "LOD = 3 × SD(blancos)",
       x = "Límite de Detección",
       y = "Frecuencia") +
  theme_minimal()

print(p5)

# Intervalo de confianza del LOD
ic_lod <- quantile(lod_bootstrap, c(0.025, 0.975))
cat("Intervalo de confianza 95% para LOD:", ic_lod[1], "-", ic_lod[2], "\n")
Intervalo de confianza 95% para LOD: 0.002683614 - 0.005776629 

Ejemplo 4: Comparación de Métodos Analíticos

Datos de Comparación

# Resultados de dos métodos analíticos para la misma muestra
metodo_A <- c(15.2, 15.4, 15.1, 15.3, 15.5, 15.0, 15.2, 15.4)
metodo_B <- c(15.8, 15.6, 15.9, 15.7, 15.5, 15.8, 15.6, 15.7)

# Bootstrap de dos muestras
bootstrap_diff <- two.boot(metodo_A, metodo_B, mean, R = 10000)

# Intervalo de confianza para la diferencia
ic_diff <- boot.ci(bootstrap_diff, type = "perc", conf = 0.95)
print(ic_diff)
BOOTSTRAP CONFIDENCE INTERVAL CALCULATIONS
Based on 10000 bootstrap replicates

CALL : 
boot.ci(boot.out = bootstrap_diff, conf = 0.95, type = "perc")

Intervals : 
Level     Percentile     
95%   (-0.575, -0.300 )  
Calculations and Intervals on Original Scale

Visualización de Comparación

# Crear dataframe para comparación
metodos_df <- data.frame(
  valor = c(metodo_A, metodo_B),
  metodo = rep(c("Método A", "Método B"), each = 8)
)

# Boxplot comparativo
p6 <- ggplot(metodos_df, aes(x = metodo, y = valor, fill = metodo)) +
  geom_boxplot(alpha = 0.7) +
  geom_jitter(width = 0.2, alpha = 0.6, size = 2) +
  labs(title = "Comparación de Métodos Analíticos",
       x = "Método",
       y = "Resultado (mg/L)") +
  theme_minimal() +
  theme(legend.position = "none")

# Distribución de la diferencia bootstrap
diff_df <- data.frame(diferencia = bootstrap_diff$t)

p7 <- ggplot(diff_df, aes(x = diferencia)) +
  geom_histogram(bins = 50, fill = "purple", alpha = 0.7) +
  geom_vline(xintercept = 0, color = "red", linetype = "dashed", size = 1) +
  labs(title = "Distribución Bootstrap de la Diferencia de Medias",
       subtitle = "Método A - Método B",
       x = "Diferencia de Medias",
       y = "Frecuencia") +
  theme_minimal()

# Mostrar gráficos lado a lado
gridExtra::grid.arrange(p6, p7, ncol = 2)

Volver arriba

Referencias

Davison, A. C., y D. V. Hinkley. 1997. Bootstrap Methods and Their Application. Cambridge University Press.
Efron, Bradley. 1979. «Bootstrap Methods: Another Look at the Jackknife». The Annals of Statistics 7 (1): 1-26. https://doi.org/10.1214/aos/1176344552.
González, A. G., y M. A. Herrador. 2010. «Application of resampling methods to method validation in analytical chemistry». Analytica Chimica Acta 691 (1-2): 18-25. https://doi.org/10.1016/j.aca.2010.02.012.

Copyright 2024, Carlos Gómez