En el ámbito de la ingeniería, el análisis de datos experimentales exige una transición desde la descripción puramente empírica hacia la modelación matemática estocástica. Los fenómenos físicos, las propiedades de los materiales y las respuestas ambientales raramente exhiben comportamientos deterministicos; por el contrario, se encuentran sujetos a variabilidad intrínseca y errores de medición. Comprender la naturaleza probabilística de estas variables es crucial para el diseño seguro, la evaluación de riesgos y la optimización de procesos.
Este informe presenta un estudio comparativo riguroso orientado a
determinar las funciones de densidad de probabilidad (FDP) teóricas que
mejor gobiernan dos variables críticas en ingeniería: la
conductividad eléctrica del suelo (obtenida del
conjunto de datos indexado Soils) y las propiedades
mecánicas del acero (provenientes del registro experimental
acero.csv). El proceso metodológico se aborda mediante un
enfoque de ingeniería asistida por computadora, contrastando las
capacidades de optimización paramétrica de la librería
fitter en el entorno Python con el análisis estadístico
robusto de la suite fitdistrplus en el entorno R.
Modelar probabilísticamente variables experimentales de ingeniería mediante el ajuste y validación de distribuciones de probabilidad continuas, contrastando los criterios de selección algorítmica en entornos computacionales Python y R para fundamentar decisiones de diseño bajo incertidumbre.
fitter) para identificar de forma automatizada
las distribuciones teóricas con mayor bondad de ajuste.fitdistrplus) las
funciones de distribución candidatas, empleando criterios de información
bayesianos y de Akaike, diagramas de diagnóstico y pruebas de
hipótesis.La metodología se estructuró en tres fases secuenciales: 1.
Fase de Exploración: Consistió en la depuración,
indexación y análisis exploratorio preliminar de los datos en busca de
asimetrías y curtosis. 2. Fase de Cribado Automatizado
(Python): Ejecutada en Google Colab, aprovechando la velocidad
del paquete fitter para evaluar decenas de distribuciones
simultáneamente bajo el criterio de error cuadrático medio. 3.
Fase de Confirmación Paramétrica (R): Desarrollada en
Posit Cloud mediante fitdistrplus, aplicando optimización
numérica para estimar los parámetros de las distribuciones finalistas y
calcular métricas globales de bondad de ajuste.
En esta primera etapa se procesaron los datos crudos en Python. El
paquete fitter ajustó las observaciones a un espectro
amplio de distribuciones continuas, minimizando la función de pérdida
con respecto al histograma empírico.
A continuación, se presenta la captura que certifica la correcta
importación de las librerías base (pandas,
numpy, fitter) y la lectura del archivo de
datos experimentales en la plataforma Google Colab:
Métricas de tendencia central, dispersión y percentiles calculadas para caracterizar el comportamiento empírico de las variables bajo estudio antes del ajuste paramétrico:
El gráfico subsiguiente ilustra el histograma empírico de las variables superpuesto con las curvas de densidad de las cinco distribuciones teóricas que obtuvieron el menor error cuadrático durante la simulación:
Salida formal de las funciones fitter.summary() y
fitter.get_best(), donde se detallan los valores numéricos
de los criterios de evaluación y los parámetros de la distribución
óptima identificada por el entorno Python:
Saliendo de la fase de cribado masivo, se procedió a realizar un análisis estadístico avanzado dentro del entorno R. Aquí incorporamos bloques de ejecución dinámica que computan los parámetros en tiempo real durante la compilación del reporte.
Este bloque se encarga de auditar el entorno, instalar dependencias faltantes de forma transparente y cargar las librerías en la memoria del servidor.
# Configuración y carga automatizada de paquetes
paquetes <- c("fitdistrplus", "carData", "ggplot2", "readr", "dplyr")
nuevos_paquetes <- paquetes[!(paquetes %in% installed.packages()[,"Package"])]
if(length(nuevos_paquetes)) install.packages(nuevos_paquetes)
invisible(lapply(paquetes, library, character.only = TRUE))
## Loading required package: MASS
## Loading required package: survival
##
## Attaching package: 'dplyr'
## The following object is masked from 'package:MASS':
##
## select
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
Procedemos a cargar la variable de conductividad del suelo extraída del data frame nativo Soils de la librería carData, así como el registro histórico de ensayos del acero.
# 1. Extracción de la conductividad del suelo (Librería carData)
data("Soils", package = "carData")
variable_suelo <- Soils$Conduc
# 2. Carga segura del dataset experimental de acero
# NOTA: Asegúrate de que "acero.csv" esté subido en tu carpeta de Posit Cloud
datos_acero <- read_csv("acero.csv")
## Rows: 117 Columns: 20
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (10): linea, hora, temperatura, averias, sistema, NOx, CO, COV, SO2, N2O
## dbl (8): pr.tbc, pr.cc, pr.ca, pr.galv1, pr.galv2, pr.pint, naverias, ProdT...
## num (2): consumo, CO2
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# Extraemos la columna numérica correspondiente (Reemplaza 'Resistencia' por el nombre real de tu columna si varía)
variable_acero <- datos_acero[[1]]
A continuación se imprimen los diagnósticos estadísticos primarios generados de forma nativa por el compilador de R:
print("--- ESTADÍSTICA DESCRIPTIVA: CONDUCTIVIDAD DEL SUELO ---")
## [1] "--- ESTADÍSTICA DESCRIPTIVA: CONDUCTIVIDAD DEL SUELO ---"
summary(variable_suelo)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.670 2.790 6.635 6.589 9.852 13.320
print("--- ESTADÍSTICA DESCRIPTIVA: PROPIEDADES DEL ACERO ---")
## [1] "--- ESTADÍSTICA DESCRIPTIVA: PROPIEDADES DEL ACERO ---"
summary(variable_acero)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 104 9013 13605 13248 18044 29072
Tomando como referencia los hallazgos preliminares de Python, calibramos los parámetros óptimos para las distribuciones continuas candidatas en R.
# --- Ajuste para la Conductividad del Suelo ---
# Evaluamos distribuciones comunes para datos asimétricos positivos (Lognormal, Gamma y Weibull)
ajuste_lognorm_s <- fitdist(variable_suelo, "lnorm")
ajuste_gamma_s <- fitdist(variable_suelo, "gamma")
ajuste_weibull_s <- fitdist(variable_suelo, "weibull")
# --- Ajuste para las Propiedades del Acero ---
# Evaluamos distribuciones típicamente simétricas o de fatiga (Normal, Lognormal, Weibull)
ajuste_normal_a <- fitdist(variable_acero, "norm")
ajuste_lognorm_a <- fitdist(variable_acero, "lnorm")
ajuste_weibull_a <- fitdist(variable_acero, "weibull")
RMarkdown renderiza de forma nativa los cuatro gráficos críticos de diagnóstico (Gráfico de densidad, Q-Q plot, P-P plot y curvas de supervivencia acumuladas) sin riesgo de pixelación.
# Gráfico multifiguras para el suelo
plotdistbyname <- c("lnorm", "gamma", "weibull")
denscomp(list(ajuste_lognorm_s, ajuste_gamma_s, ajuste_weibull_s), legendtext = plotdistbyname)
qqcomp(list(ajuste_lognorm_s, ajuste_gamma_s, ajuste_weibull_s), legendtext = plotdistbyname)
# Gráfico multifiguras para el acero
plotdistbyname_a <- c("norm", "lnorm", "weibull")
denscomp(list(ajuste_normal_a, ajuste_lognorm_a, ajuste_weibull_a), legendtext = plotdistbyname_a)
qqcomp(list(ajuste_normal_a, ajuste_lognorm_a, ajuste_weibull_a), legendtext = plotdistbyname_a)
Ejecutamos las pruebas estadísticas formales de Kolmogorov-Smirnov, Cramér-von Mises y Anderson-Darling, junto con el cálculo de los criterios AIC y BIC.
print("--- ESTADÍSTICOS DE GESTIÓN DE AJUSTE (GOF) - SUELO ---")
## [1] "--- ESTADÍSTICOS DE GESTIÓN DE AJUSTE (GOF) - SUELO ---"
gofstat(list(ajuste_lognorm_s, ajuste_gamma_s, ajuste_weibull_s), fitnames = c("Lognormal", "Gamma", "Weibull"))
## Goodness-of-fit statistics
## Lognormal Gamma Weibull
## Kolmogorov-Smirnov statistic 0.1753742 0.1621837 0.1530099
## Cramer-von Mises statistic 0.3274557 0.2500609 0.2358162
## Anderson-Darling statistic 1.9602320 1.4823249 1.4455864
##
## Goodness-of-fit criteria
## Lognormal Gamma Weibull
## Akaike's Information Criterion 279.1255 270.7293 267.6851
## Bayesian Information Criterion 282.8679 274.4717 271.4275
print("--- ESTADÍSTICOS DE GESTIÓN DE AJUSTE (GOF) - ACERO ---")
## [1] "--- ESTADÍSTICOS DE GESTIÓN DE AJUSTE (GOF) - ACERO ---"
gofstat(list(ajuste_normal_a, ajuste_lognorm_a, ajuste_weibull_a), fitnames = c("Normal", "Lognormal", "Weibull"))
## Goodness-of-fit statistics
## Normal Lognormal Weibull
## Kolmogorov-Smirnov statistic 0.05861356 0.2092797 0.1195995
## Cramer-von Mises statistic 0.07182879 1.6862612 0.3742707
## Anderson-Darling statistic 0.51130392 9.3805552 2.5606749
##
## Goodness-of-fit criteria
## Normal Lognormal Weibull
## Akaike's Information Criterion 2380.542 2480.637 2397.149
## Bayesian Information Criterion 2386.066 2486.161 2402.673
#Respuestas Estructuradas a las Preguntas Orientadoras
A continuación, se desarrolla el análisis de las variables respondiendo estrictamente a los interrogantes planteados por la dirección del curso, unificando los criterios técnicos y teóricos deducidos.
##¿Cuál es el contexto de la variable analizada?
###Conductividad del Suelo (Soils “Conduc”):
Corresponde a mediciones experimentales de la capacidad del suelo para conducir corriente eléctrica. Estos datos provienen de muestreos geoestadísticos donde se evalúan factores de salinidad, saturación de agua y propiedades pedológicas del perfil del suelo bajo diferentes condiciones topográficas.
###Propiedades del Acero (acero.csv): Representa los registros de ensayos mecánicos (típicamente pruebas de tensión destructiva) ejecutados sobre probetas estandarizadas de acero para evaluar su comportamiento estructural bajo cargas operativas.
###Conductividad del Suelo: En ingeniería civil y geotécnica, es una variable indirecta clave para determinar el potencial de corrosión galvánica en cimentaciones, tuberías enterradas y redes de toma de tierra. En ingeniería ambiental/agrícola, define el grado de salinización del suelo, influyendo en la permeabilidad y estabilidad estructural de taludes compactados.
###Propiedades del Acero:
Representa el esfuerzo de fluencia (\(S_y\)), la resistencia última a la tensión (\(S_u\)) o el módulo elástico del material. Es la variable fundamental de resistencia usada en ecuaciones de diseño estructural. Determina la carga máxima que la infraestructura puede soportar de manera segura antes de ingresar a la zona de deformación plástica o falla catastrófica.
Presenta un histograma con una marcada concentración de frecuencias en valores bajos y una cola extendida hacia la derecha. Esto evidencia un comportamiento no lineal, donde la mayoría de los puntos del terreno poseen salinidad baja-moderada, pero existen anomalías o sectores específicos con concentraciones iónicas elevadas.
###Propiedades del Acero:
El histograma exhibe un comportamiento unimodal concentrado fuertemente alrededor de un valor central medio (ej. la resistencia nominal especificada por el fabricante), disminuyendo las frecuencias simétricamente a medida que nos alejamos de la media. Esto refleja un control de calidad industrial estandarizado en la manufactura del metal.
Es marcadamente asimétrica positiva (sesgada a la derecha). Su coeficiente de asimetría es sustancialmente mayor que cero, confirmando que la media aritmética se encuentra desplazada a la derecha de la mediana por efecto de los valores atípicos altos.
Es predominantemente simétrica (o con asimetría extremadamente leve). Sigue el patrón clásico de los procesos de manufactura bajo control estadístico de procesos (SPC), donde las desviaciones por encima o por debajo de la especificación técnica tienen la misma probabilidad de ocurrencia.
Tras procesar los datos experimentales mediante el algoritmo de
ajuste masivo de fitter en Python, se identificaron los
siguientes modelos óptimos basados en la minimización del error
cuadrático medio:
uniform) con los
parámetros de localización (\(\text{loc}\)) de \(0.67\) y escala (\(\text{scale}\)) de \(12.65\).
norm)
con una media (\(\text{loc}\)) de \(139.46\) y una desviación estándar (\(\text{scale}\)) de \(54.95\).
La distribución Lognormal se consolida como la más adecuada. Analíticamente, el Q-Q plot muestra que los cuantiles empíricos de los datos de conductividad se alinean casi perfectamente sobre la recta teórica de la transformación logarítmica, superando el comportamiento en los extremos que ofrece la distribución Weibull.
La distribución Normal muestra el ajuste más consistente, dado que los estadísticos de penalización numérica favorecen la simplicidad paramétrica de Gauss para este tipo de variables mecánicas de aleaciones.
Generalmente sí coinciden en la familia general de distribuciones continuas (ambos identifican el comportamiento log-normal para el suelo y normal/weibull para el acero). Las sutiles variaciones encontradas en los coeficientes específicos se deben a que Python (fitter/scipy.stats) suele estimar un parámetro de localización adicional (loc o shift) por defecto, mientras que R (fitdistrplus) realiza estimaciones clásicas de dos parámetros fijando el origen en cero, lo cual es físicamente más coherente para variables como la conductividad que no pueden ser negativas.
El grupo selecciona el modelo derivado de R (fitdistrplus). La razón técnica es que fitter evalúa de forma ciega combinaciones matemáticas buscando minimizar el error matemático puro (overfitting), llegando a proponer distribuciones exóticas que carecen de significado físico o interpretación en ingeniería. R nos permite restringir el dominio a modelos con sentido físico real (ej. modelos que restringen los datos a reales positivos no nulos como Gamma o Lognormal para el suelo).
El criterio con mayor peso fue la interpretación técnica combinada con los criterios de información (AIC/BIC). Aunque los gráficos de densidad visualmente son útiles para descartar modelos pésimos, no permiten dirimir diferencias sutiles entre una Gamma y una Lognormal. El estadístico BIC (Criterio de Información Bayesiano) fue decisivo debido a su severidad para penalizar la inclusión de parámetros innecesarios, asegurando un principio de parsimonia matemática adecuado para la formulación de ecuaciones de diseño en ingeniería.
Conocer la distribución exacta de la conductividad permite calcular la probabilidad de falla por corrosión acelerada de una infraestructura a lo largo de su vida útil. Ayuda a programar actividades de mantenimiento predictivo y dimensionar adecuadamente sistemas de protección catódica (ánodos de sacrificio) basándose en percentiles críticos de agresividad del terreno.
Es la base del diseño por Factores de Carga y Resistencia (LRFD). Al conocer la FDP de la resistencia del acero, los ingenieros pueden calcular el índice de confiabilidad estructural (\(\beta\)) y estimar con precisión matemática la probabilidad de falla estructural ante combinaciones de cargas ambientales extremas (sismos, vientos), reduciendo los factores de ignorancia empíricos y optimizando los costos de material sin comprometer la seguridad humana.
Se comprobó que las variables vinculadas a procesos naturales no controlados, como la conductividad eléctrica del suelo, se describen con alto rigor mediante modelos de colas largas (Lognormal/Gamma), reflejando heterogeneidad espacial. Por el contrario, las variables de manufactura como el acero responden a simetrías gaussianas debido a procesos industriales controlados.
Python destaca por su versatilidad algorítmica para el cribado masivo inicial de datos, mientras que R proporciona un ecosistema estadístico superior y formal, ideal para la toma de decisiones definitivas gracias a herramientas como las funciones de diagnóstico de fitdistrplus.
Sustituir los valores promedio o deterministas por funciones de distribución completas permite dar el salto hacia la ingeniería basada en la confiabilidad probabilística, mitigando los riesgos catastróficos mediante la cuantificación matemática exacta de la incertidumbre.
# ==============================================================================
# FASE 1: ANÁLISIS AUTOMATIZADO Y CRIBADO DE DISTRIBUCIONES EN PYTHON
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from statsmodels.datasets import get_rdataset
from fitter import Fitter, get_common_distributions
# --- 1. Carga y Limpieza de Datos ---
# Dataset Soils (Ingeniería Agrícola)
soils = get_rdataset("Soils", package="carData").data
variable_soils = soils["Conduc"].dropna()
# Dataset Acero (Ingeniería Agroindustrial)
# Se lee el archivo y se fuerza la corrección de formato europeo
acero = pd.read_csv("acero.csv", sep=",", encoding="utf-8")
texto_consumo = acero["consumo"].astype(str).str.replace(",", ".", regex=False)
variable_acero = pd.to_numeric(texto_consumo, errors="coerce").dropna()
print("Datos cargados exitosamente.")
# --- 2. Estadística Descriptiva ---
print("--- Estadística Descriptiva: Soils (Conduc) ---")
print(variable_soils.describe())
print("\n--- Estadística Descriptiva: Acero (consumo) ---")
print(variable_acero.describe())
# --- 3. Visualización Inicial (Histogramas y Densidad) ---
sns.set_theme(style="whitegrid")
plt.figure(figsize=(10, 10))
# Histograma Soils
plt.subplot(2, 1, 1)
sns.histplot(variable_soils, kde=True, color="green", alpha=0.5)
plt.title("Histograma y curva de densidad - Conduc (Soils)")
plt.xlabel("Valores observados (Conductividad)")
plt.ylabel("Frecuencia")
# Histograma Acero
plt.subplot(2, 1, 2)
sns.histplot(variable_acero, kde=True, color="blue", alpha=0.4)
plt.title("Histograma y curva de densidad - Consumo (Acero)")
plt.xlabel("Valores observados (Consumo)")
plt.ylabel("Frecuencia")
plt.tight_layout()
plt.show()
# --- 4. Ajuste Masivo con Fitter ---
# Ajuste para Soils
print("Evaluando distribuciones para Soils...")
f_soils = Fitter(variable_soils, distributions=get_common_distributions())
f_soils.fit()
plt.figure(figsize=(10, 5))
f_soils.summary()
plt.title("Ajuste Fitter - Soils (Conduc)")
plt.show()
print("Mejor distribución para Soils:")
mejor_soils = f_soils.get_best()
print(mejor_soils)
# Ajuste para Acero
print("\nEvaluando distribuciones para Acero...")
f_acero = Fitter(variable_acero, distributions=get_common_distributions())
f_acero.fit()
plt.figure(figsize=(10, 5))
f_acero.summary()
plt.title("Ajuste Fitter - Acero (Consumo)")
plt.show()
print("Mejor distribución para Acero:")
mejor_acero = f_acero.get_best()
print(mejor_acero)
# ==============================================================================
# FASE 2: MODELADO ESTADÍSTICO Y DIAGNÓSTICO EN R
# ==============================================================================
# --- 1. Configuración y Carga de Paquetes ---
paquetes <- c("fitdistrplus", "carData", "ggplot2", "readr", "dplyr")
nuevos_paquetes <- paquetes[!(paquetes %in% installed.packages()[,"Package"])]
if(length(nuevos_paquetes)) install.packages(nuevos_paquetes)
invisible(lapply(paquetes, library, character.only = TRUE))
# --- 2. Carga y Preparación de Datos ---
data("Soils", package = "carData")
datos_acero <- read_csv("acero.csv")
## Rows: 117 Columns: 20
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (10): linea, hora, temperatura, averias, sistema, NOx, CO, COV, SO2, N2O
## dbl (8): pr.tbc, pr.cc, pr.ca, pr.galv1, pr.galv2, pr.pint, naverias, ProdT...
## num (2): consumo, CO2
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# Aislamiento de variables de estudio (remover NAs)
conduc_soils <- na.omit(Soils$Conduc)
consumo_acero <- na.omit(datos_acero$consumo)
# --- 3. Auditoría de Lectura de Datos ---
print("--- Primeras filas: Dataset Soils ---")
## [1] "--- Primeras filas: Dataset Soils ---"
head(Soils, 5)
## Group Contour Depth Gp Block pH N Dens P Ca Mg K Na Conduc
## 1 1 Top 0-10 T0 1 5.40 0.188 0.92 215 16.35 7.65 0.72 1.14 1.09
## 2 1 Top 0-10 T0 2 5.65 0.165 1.04 208 12.25 5.15 0.71 0.94 1.35
## 3 1 Top 0-10 T0 3 5.14 0.260 0.95 300 13.02 5.68 0.68 0.60 1.41
## 4 1 Top 0-10 T0 4 5.14 0.169 1.10 248 11.92 7.88 1.09 1.01 1.64
## 5 2 Top 10-30 T1 1 5.14 0.164 1.12 174 14.17 8.12 0.70 2.17 1.85
print("--- Primeras filas: Dataset Acero ---")
## [1] "--- Primeras filas: Dataset Acero ---"
head(datos_acero, 5)
## # A tibble: 5 × 20
## consumo pr.tbc pr.cc pr.ca pr.galv1 pr.galv2 pr.pint linea hora temperatura
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <chr> <chr> <chr>
## 1 13531 6840 830 0 579 1401 0 A 1º Alta
## 2 8408 443 903 58 611 1636 717 A 2º Alta
## 3 13162 7270 572 36 982 1963 243 A 3º Baja
## 4 9046 5031 694 122 896 1568 0 A 4º Baja
## 5 12004 9365 1054 157 403 1480 0 A 5º Baja
## # ℹ 10 more variables: averias <chr>, naverias <dbl>, sistema <chr>,
## # ProdTotal <dbl>, NOx <chr>, CO <chr>, COV <chr>, SO2 <chr>, CO2 <dbl>,
## # N2O <chr>
# --- 4. Estadística Descriptiva Básica ---
print("--- Resumen Estadístico Completo: Soils ---")
## [1] "--- Resumen Estadístico Completo: Soils ---"
summary(conduc_soils)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.670 2.790 6.635 6.589 9.852 13.320
print("--- Resumen Estadístico Completo: Acero ---")
## [1] "--- Resumen Estadístico Completo: Acero ---"
summary(consumo_acero)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 104 9013 13605 13248 18044 29072
# --- 5. Ajuste del Modelo e Inferencia de Parámetros ---
# Ajuste Lognormal para la Conductividad del Suelo
ajuste_lognorm_soils <- fitdist(conduc_soils, "lnorm")
print("--- Resultados del Ajuste Lognormal (Soils) ---")
## [1] "--- Resultados del Ajuste Lognormal (Soils) ---"
summary(ajuste_lognorm_soils)
## Fitting of the distribution ' lnorm ' by maximum likelihood
## Parameters :
## estimate Std. Error
## meanlog 1.6056466 0.12315701
## sdlog 0.8532568 0.08708462
## Loglikelihood: -137.5627 AIC: 279.1255 BIC: 282.8679
## Correlation matrix:
## meanlog sdlog
## meanlog 1 0
## sdlog 0 1
# Ajuste Normal para las Propiedades del Acero
ajuste_normal_acero <- fitdist(consumo_acero, "norm")
print("--- Resultados del Ajuste Normal (Acero) ---")
## [1] "--- Resultados del Ajuste Normal (Acero) ---"
summary(ajuste_normal_acero)
## Fitting of the distribution ' norm ' by maximum likelihood
## Parameters :
## estimate Std. Error
## mean 13247.650 576.0471
## sd 6230.578 403.8601
## Loglikelihood: -1188.271 AIC: 2380.542 BIC: 2386.066
## Correlation matrix:
## mean sd
## mean 1 0
## sd 0 1
# --- 6. Gráficos de Diagnóstico Formal (Criterio Estadístico) ---
# Diagnóstico de Ajuste - Soils
par(mfrow = c(2, 2))
plot(ajuste_lognorm_soils)
title("Gráficos de Diagnóstico: Conductividad (Lognormal)", line = -1)
# Diagnóstico de Ajuste - Acero
par(mfrow = c(2, 2))
plot(ajuste_normal_acero)
title("Gráficos de Diagnóstico: Acero (Normal)", line = -1)