Diseño factorial fraccionado Modelo interactivo Publicación web

Informe estadístico con enfoque profesional

Este documento presenta el análisis del diseño \(2^{5-1}\), compara la fracción principal, la fracción complementaria y el diseño completo, e integra tablas dinámicas, gráficos interactivos, diagnóstico de supuestos y una decisión operativa final.

<div class="icon">📊</div>
<h3>Exploración</h3>
<p>Se revisan las corridas experimentales, los factores codificados y la respuesta de rendimiento.</p>
<div class="icon">🧪</div>
<h3>Modelamiento</h3>
<p>Se ajustan modelos lineales para efectos principales e interacciones de dos factores.</p>
<div class="icon">🔎</div>
<h3>Validación</h3>
<p>Se verifican supuestos mediante pruebas estadísticas y diagnósticos gráficos interactivos.</p>
<div class="icon">✅</div>
<h3>Decisión</h3>
<p>Se comparan efectos, significancia y niveles recomendados para definir el mejor tratamiento.</p>

1 Resumen ejecutivo

Objetivo del informe: determinar si la fracción principal del diseño factorial fraccionado \(2^{5-1}\) es suficiente para identificar los factores relevantes del proceso o si el diseño completo \(2^5\) aporta información necesaria para una decisión final más confiable.

El análisis se desarrolla en tres niveles: primero se verifica la estructura del fraccionamiento; luego se estiman efectos principales e interacciones; finalmente se comparan los resultados entre la fracción principal, la fracción complementaria y el diseño completo para seleccionar los niveles que maximizan el rendimiento.

2 Planteamiento del experimento

Se analiza un diseño factorial fraccionado \(2^{5-1}\) aplicado a un proceso de fabricación de semiconductores. La variable de respuesta es Rendimiento.

Los factores son:

Factor Descripción Nivel bajo (-1) Nivel alto (+1)
A Nivel de abertura Pequeña Grande
B Tiempo de exposición 20% abajo 20% arriba
C Tiempo de revelado 30 segundos 45 segundos
D Dimensión de la máscara Pequeña Grande
E Tiempo de grabado 14.5 min 15.5 min

Se comparan tres escenarios:

  1. Fracción principal del diseño \(2^{5-1}\).
  2. Fracción complementaria del diseño \(2^{5-1}\).
  3. Diseño factorial completo \(2^5\), obtenido al combinar ambas fracciones.

La pregunta central es si la fracción principal permite detectar los mismos factores relevantes que el diseño completo, o si es necesario ejecutar el factorial completo para tomar decisiones confiables.

3 Carga y preparación de los datos

Importante para ejecutar el informe: el archivo de Excel debe estar en la misma carpeta que este RMarkdown. De esta forma, el documento podrá compilarse correctamente como HTML interactivo.
archivo <- "matriz_diseno_factorial_fraccionado_2_5menos1.xlsx"

hojas <- readxl::excel_sheets(archivo)
print(hojas)
## [1] "Principal_Rcmdr"      "Complementaria_Rcmdr" "Completo_32"         
## [4] "Verificacion"         "Notas"                "Tabla_Imagen"
leer_hoja <- function(nombre) {
  if (!nombre %in% hojas) {
    stop(paste("No se encontró la hoja:", nombre, ". Revise el nombre en el Excel."))
  }
  readxl::read_excel(archivo, sheet = nombre)
}

preparar_datos <- function(datos, nombre_fraccion) {
  datos %>%
    mutate(
      across(c(A, B, C, D, E), as.numeric),
      Rendimiento = as.numeric(Rendimiento),
      Corrida = row_number(),
      Fraccion_Analisis = nombre_fraccion
    )
}

principal <- leer_hoja("Principal_Rcmdr") %>% preparar_datos("Fracción principal")
complementaria <- leer_hoja("Complementaria_Rcmdr") %>% preparar_datos("Fracción complementaria")
completo <- leer_hoja("Completo_32") %>% preparar_datos("Diseño completo")

DT::datatable(principal, caption = "Fracción principal", options = list(pageLength = 16, scrollX = TRUE), rownames = FALSE)
DT::datatable(complementaria, caption = "Fracción complementaria", options = list(pageLength = 16, scrollX = TRUE), rownames = FALSE)
DT::datatable(completo, caption = "Diseño completo", options = list(pageLength = 32, scrollX = TRUE), rownames = FALSE)

4 Metodología visual del análisis

El flujo de trabajo estadístico se organiza desde la lectura de datos hasta la recomendación final del mejor tratamiento. Esta secuencia facilita la lectura del informe en formato web y permite entender la lógica del análisis antes de revisar los resultados numéricos.

5 Estructura del fraccionamiento

Para el diseño \(2^{5-1}\), la relación generadora es:

\[ I = ABCDE \]

Esto corresponde a un diseño de resolución V. En términos prácticos:

  • Los efectos principales no se confunden con interacciones de dos factores.
  • Las interacciones de dos factores se confunden con interacciones de tres factores.
  • La fracción complementaria permite completar el diseño y verificar si la fracción principal conserva la misma información relevante.
verificar_generador <- function(datos) {
  datos %>%
    mutate(ABCDE = A * B * C * D * E) %>%
    count(ABCDE)
}

DT::datatable(verificar_generador(principal), caption = "Signo ABCDE en la fracción principal", rownames = FALSE)
DT::datatable(verificar_generador(complementaria), caption = "Signo ABCDE en la fracción complementaria", rownames = FALSE)
DT::datatable(verificar_generador(completo), caption = "Signo ABCDE en el diseño completo", rownames = FALSE)

6 Modelos lineales

Para las fracciones de 16 corridas se usa un modelo de cribado con efectos principales:

\[ Rendimiento = \beta_0 + \beta_A A + \beta_B B + \beta_C C + \beta_D D + \beta_E E + \varepsilon \]

Para el diseño completo se ajustan dos modelos:

  1. Modelo de efectos principales.
  2. Modelo con efectos principales e interacciones de dos factores.
modelo_principal <- lm(Rendimiento ~ A + B + C + D + E, data = principal)
modelo_complementaria <- lm(Rendimiento ~ A + B + C + D + E, data = complementaria)
modelo_completo_main <- lm(Rendimiento ~ A + B + C + D + E, data = completo)
modelo_completo_2fi <- lm(Rendimiento ~ (A + B + C + D + E)^2, data = completo)

resumen_modelo <- function(modelo, nombre) {
  broom::glance(modelo) %>%
    mutate(Modelo = nombre) %>%
    select(Modelo, r.squared, adj.r.squared, sigma, statistic, p.value, df, df.residual, AIC, BIC)
}

resumenes_modelos <- bind_rows(
  resumen_modelo(modelo_principal, "Fracción principal: efectos principales"),
  resumen_modelo(modelo_complementaria, "Fracción complementaria: efectos principales"),
  resumen_modelo(modelo_completo_main, "Diseño completo: efectos principales"),
  resumen_modelo(modelo_completo_2fi, "Diseño completo: efectos principales + interacciones 2FI")
)

DT::datatable(redondear_numericas(resumenes_modelos, 4), caption = "Resumen comparativo de modelos", options = list(scrollX = TRUE), rownames = FALSE)

7 Coeficientes, efectos y significancia

En un diseño codificado con niveles \(-1\) y \(+1\), el efecto estimado se obtiene como:

\[ Efecto = 2 \times \hat{\beta} \]

extraer_efectos <- function(modelo, nombre) {
  broom::tidy(modelo) %>%
    filter(term != "(Intercept)") %>%
    mutate(
      Modelo = nombre,
      Efecto = 2 * estimate,
      Abs_Efecto = abs(Efecto),
      Abs_t = abs(statistic),
      Significativo_5pct = if_else(p.value < 0.05, "Sí", "No"),
      t_critico_5pct = qt(0.975, df.residual(modelo))
    ) %>%
    select(Modelo, term, estimate, Efecto, Abs_Efecto, std.error, statistic, Abs_t, p.value, Significativo_5pct, t_critico_5pct) %>%
    arrange(desc(Abs_Efecto))
}

efectos_principal <- extraer_efectos(modelo_principal, "Fracción principal")
efectos_complementaria <- extraer_efectos(modelo_complementaria, "Fracción complementaria")
efectos_completo_main <- extraer_efectos(modelo_completo_main, "Diseño completo: efectos principales")
efectos_completo_2fi <- extraer_efectos(modelo_completo_2fi, "Diseño completo: principales + 2FI")

DT::datatable(redondear_numericas(efectos_principal, 4), caption = "Efectos estimados - Fracción principal", options = list(pageLength = 10, scrollX = TRUE), rownames = FALSE)
DT::datatable(redondear_numericas(efectos_complementaria, 4), caption = "Efectos estimados - Fracción complementaria", options = list(pageLength = 10, scrollX = TRUE), rownames = FALSE)
DT::datatable(redondear_numericas(efectos_completo_2fi, 4), caption = "Efectos estimados - Diseño completo con interacciones 2FI", options = list(pageLength = 15, scrollX = TRUE), rownames = FALSE)

8 Tabla ANOVA

tabla_anova <- function(modelo, nombre) {
  broom::tidy(anova(modelo)) %>%
    mutate(Modelo = nombre) %>%
    select(Modelo, term, df, sumsq, meansq, statistic, p.value)
}

anova_total <- bind_rows(
  tabla_anova(modelo_principal, "Fracción principal"),
  tabla_anova(modelo_complementaria, "Fracción complementaria"),
  tabla_anova(modelo_completo_main, "Diseño completo: efectos principales"),
  tabla_anova(modelo_completo_2fi, "Diseño completo: principales + 2FI")
)

DT::datatable(redondear_numericas(anova_total, 4), caption = "Tablas ANOVA", options = list(pageLength = 20, scrollX = TRUE), rownames = FALSE)

9 Pruebas de supuestos

Se evalúan tres supuestos del modelo lineal:

  • Normalidad de residuos: prueba de Shapiro-Wilk.
  • Homocedasticidad: prueba de Breusch-Pagan.
  • Independencia: prueba de Durbin-Watson.
prueba_shapiro_segura <- function(residuos) {
  if (length(residuos) < 3 || length(unique(round(residuos, 10))) < 3) {
    return(tibble(Estadistico = NA_real_, p.value = NA_real_))
  }
  out <- shapiro.test(residuos)
  tibble(Estadistico = unname(out$statistic), p.value = out$p.value)
}

prueba_bp_segura <- function(modelo) {
  out <- tryCatch(lmtest::bptest(modelo), error = function(e) NULL)
  if (is.null(out)) return(tibble(Estadistico = NA_real_, p.value = NA_real_))
  tibble(Estadistico = unname(out$statistic), p.value = out$p.value)
}

prueba_dw_segura <- function(modelo) {
  out <- tryCatch(lmtest::dwtest(modelo), error = function(e) NULL)
  if (is.null(out)) return(tibble(Estadistico = NA_real_, p.value = NA_real_))
  tibble(Estadistico = unname(out$statistic), p.value = out$p.value)
}

analizar_supuestos <- function(modelo, nombre) {
  sh <- prueba_shapiro_segura(residuals(modelo)) %>% mutate(Prueba = "Normalidad: Shapiro-Wilk")
  bp <- prueba_bp_segura(modelo) %>% mutate(Prueba = "Homocedasticidad: Breusch-Pagan")
  dw <- prueba_dw_segura(modelo) %>% mutate(Prueba = "Independencia: Durbin-Watson")

  bind_rows(sh, bp, dw) %>%
    mutate(
      Modelo = nombre,
      Decision_5pct = case_when(
        is.na(p.value) ~ "No calculable",
        p.value >= 0.05 ~ "No se rechaza el supuesto",
        p.value < 0.05 ~ "Se rechaza el supuesto"
      )
    ) %>%
    select(Modelo, Prueba, Estadistico, p.value, Decision_5pct)
}

supuestos_total <- bind_rows(
  analizar_supuestos(modelo_principal, "Fracción principal"),
  analizar_supuestos(modelo_complementaria, "Fracción complementaria"),
  analizar_supuestos(modelo_completo_main, "Diseño completo: efectos principales"),
  analizar_supuestos(modelo_completo_2fi, "Diseño completo: principales + 2FI")
)

DT::datatable(redondear_numericas(supuestos_total, 4), caption = "Pruebas de supuestos", options = list(scrollX = TRUE), rownames = FALSE)

10 Diagnóstico gráfico interactivo

datos_diagnostico <- function(modelo, nombre) {
  tibble(
    Modelo = nombre,
    Orden = seq_along(residuals(modelo)),
    Ajustados = fitted(modelo),
    Residuos = residuals(modelo),
    Residuos_Estandarizados = rstandard(modelo)
  )
}

grafico_residuos_ajustados <- function(modelo, nombre) {
  aux <- datos_diagnostico(modelo, nombre)
  p <- ggplot(aux, aes(
    x = Ajustados,
    y = Residuos_Estandarizados,
    text = paste0(
      "Modelo: ", Modelo,
      "<br>Ajustado: ", round(Ajustados, 3),
      "<br>Residuo est.: ", round(Residuos_Estandarizados, 3)
    )
  )) +
    geom_hline(yintercept = 0, linetype = "dashed") +
    geom_point(size = 2.5) +
    labs(title = paste("Residuos estandarizados vs ajustados -", nombre), x = "Valores ajustados", y = "Residuos estandarizados") +
    theme_reporte()

  plotly::ggplotly(p, tooltip = "text")
}

grafico_qq <- function(modelo, nombre) {
  aux <- datos_diagnostico(modelo, nombre) %>%
    filter(is.finite(Residuos_Estandarizados))

  qq <- qqnorm(aux$Residuos_Estandarizados, plot.it = FALSE)

  qq_data <- tibble(
    Teorico = as.numeric(qq$x),
    Muestral = as.numeric(qq$y),
    Texto = paste0(
      "Modelo: ", nombre,
      "<br>Cuantil teórico: ", round(as.numeric(qq$x), 3),
      "<br>Cuantil muestral: ", round(as.numeric(qq$y), 3)
    )
  )

  q_muestral <- quantile(qq_data$Muestral, probs = c(0.25, 0.75), na.rm = TRUE)
  q_teorico <- qnorm(c(0.25, 0.75))
  pendiente <- diff(q_muestral) / diff(q_teorico)
  intercepto <- q_muestral[1] - pendiente * q_teorico[1]

  linea <- tibble(
    Teorico = range(qq_data$Teorico, na.rm = TRUE),
    Muestral = intercepto + pendiente * range(qq_data$Teorico, na.rm = TRUE)
  )

  plotly::plot_ly(
    data = qq_data,
    x = ~Teorico,
    y = ~Muestral,
    type = "scatter",
    mode = "markers",
    text = ~Texto,
    hoverinfo = "text",
    name = "Residuos"
  ) %>%
    plotly::add_lines(
      data = linea,
      x = ~Teorico,
      y = ~Muestral,
      inherit = FALSE,
      name = "Línea Q-Q",
      hoverinfo = "none"
    ) %>%
    plotly::layout(
      title = paste("Gráfico Q-Q de residuos -", nombre),
      xaxis = list(title = "Cuantiles teóricos"),
      yaxis = list(title = "Cuantiles muestrales")
    )
}

grafico_residuos_orden <- function(modelo, nombre) {
  aux <- datos_diagnostico(modelo, nombre)
  p <- ggplot(aux, aes(
    x = Orden,
    y = Residuos_Estandarizados,
    text = paste0(
      "Modelo: ", Modelo,
      "<br>Orden: ", Orden,
      "<br>Residuo est.: ", round(Residuos_Estandarizados, 3)
    )
  )) +
    geom_hline(yintercept = 0, linetype = "dashed") +
    geom_line() +
    geom_point(size = 2.5) +
    labs(title = paste("Residuos estandarizados vs orden -", nombre), x = "Orden de corrida", y = "Residuos estandarizados") +
    theme_reporte()

  plotly::ggplotly(p, tooltip = "text")
}

10.1 Fracción principal

grafico_residuos_ajustados(modelo_principal, "Fracción principal")
grafico_qq(modelo_principal, "Fracción principal")
grafico_residuos_orden(modelo_principal, "Fracción principal")

10.2 Fracción complementaria

grafico_residuos_ajustados(modelo_complementaria, "Fracción complementaria")
grafico_qq(modelo_complementaria, "Fracción complementaria")
grafico_residuos_orden(modelo_complementaria, "Fracción complementaria")

10.3 Diseño completo

grafico_residuos_ajustados(modelo_completo_2fi, "Diseño completo: principales + 2FI")
grafico_qq(modelo_completo_2fi, "Diseño completo: principales + 2FI")
grafico_residuos_orden(modelo_completo_2fi, "Diseño completo: principales + 2FI")

11 Gráficos de Pareto interactivos

El Pareto se construye con el valor absoluto del estadístico t. La línea horizontal corresponde al valor crítico bilateral al 5%.

grafico_pareto <- function(efectos, titulo) {
  aux <- efectos %>%
    arrange(Abs_t) %>%
    mutate(
      term = forcats::fct_reorder(term, Abs_t),
      Tooltip = paste0(
        "Efecto: ", term,
        "<br>Efecto estimado: ", round(Efecto, 4),
        "<br>|t|: ", round(Abs_t, 4),
        "<br>p-value: ", round(p.value, 6),
        "<br>Significativo 5%: ", Significativo_5pct
      )
    )

  tcrit <- unique(aux$t_critico_5pct)[1]

  p <- ggplot(aux, aes(x = term, y = Abs_t, text = Tooltip)) +
    geom_col() +
    geom_hline(yintercept = tcrit, linetype = "dashed") +
    coord_flip() +
    labs(
      title = titulo,
      subtitle = paste("Línea crítica t(0.975, gl residual) =", round(tcrit, 3)),
      x = "Efecto",
      y = "|t|"
    ) +
    theme_reporte()

  plotly::ggplotly(p, tooltip = "text")
}

grafico_pareto(efectos_principal, "Pareto interactivo - Fracción principal")
grafico_pareto(efectos_complementaria, "Pareto interactivo - Fracción complementaria")
grafico_pareto(efectos_completo_2fi, "Pareto interactivo - Diseño completo con interacciones 2FI")

12 Gráficos de tendencia interactivos

Estos gráficos muestran la media del rendimiento en cada nivel de cada factor.

factor_info <- tibble(
  Factor = c("A", "B", "C", "D", "E"),
  Nombre = c("Nivel de abertura", "Tiempo de exposición", "Tiempo de revelado", "Dimensión de la máscara", "Tiempo de grabado"),
  Bajo = c("Pequeña", "20% abajo", "30 segundos", "Pequeña", "14.5 min"),
  Alto = c("Grande", "20% arriba", "45 segundos", "Grande", "15.5 min")
)

grafico_tendencia <- function(datos, nombre) {
  aux <- datos %>%
    pivot_longer(cols = c(A, B, C, D, E), names_to = "Factor", values_to = "Nivel") %>%
    group_by(Factor, Nivel) %>%
    summarise(Media_Rendimiento = mean(Rendimiento, na.rm = TRUE), .groups = "drop") %>%
    left_join(factor_info, by = "Factor") %>%
    mutate(
      Nivel_Codificado = factor(Nivel, levels = c(-1, 1), labels = c("-1", "+1")),
      Nivel_Real = if_else(Nivel == -1, Bajo, Alto),
      Tooltip = paste0(
        "Factor: ", Factor, " - ", Nombre,
        "<br>Nivel codificado: ", Nivel_Codificado,
        "<br>Nivel real: ", Nivel_Real,
        "<br>Media de rendimiento: ", round(Media_Rendimiento, 3)
      )
    )

  p <- ggplot(aux, aes(x = Nivel_Codificado, y = Media_Rendimiento, group = Factor, text = Tooltip)) +
    geom_line() +
    geom_point(size = 2.8) +
    facet_wrap(~ Factor + Nombre, scales = "free_x") +
    labs(title = paste("Gráficos de tendencia -", nombre), x = "Nivel codificado", y = "Media del rendimiento") +
    theme_reporte()

  plotly::ggplotly(p, tooltip = "text")
}

grafico_tendencia(principal, "Fracción principal")
grafico_tendencia(complementaria, "Fracción complementaria")
grafico_tendencia(completo, "Diseño completo")

13 Gráficos de interacción interactivos

En el diseño completo se revisan las interacciones de dos factores con mayor magnitud.

interacciones_top <- efectos_completo_2fi %>%
  filter(str_detect(term, ":")) %>%
  arrange(desc(Abs_Efecto)) %>%
  slice_head(n = 5) %>%
  pull(term)

DT::datatable(
  efectos_completo_2fi %>% filter(term %in% interacciones_top) %>% redondear_numericas(4),
  caption = "Interacciones de dos factores con mayor magnitud en el diseño completo",
  options = list(scrollX = TRUE),
  rownames = FALSE
)
grafico_interaccion <- function(datos, par, nombre) {
  factores <- str_split(par, ":", simplify = TRUE)
  f1 <- factores[1]
  f2 <- factores[2]

  info1 <- factor_info %>% filter(Factor == f1)
  info2 <- factor_info %>% filter(Factor == f2)

  aux <- datos %>%
    mutate(
      Nivel_x = factor(.data[[f1]], levels = c(-1, 1), labels = c("-1", "+1")),
      Nivel_linea = factor(.data[[f2]], levels = c(-1, 1), labels = c("-1", "+1")),
      Nivel_x_real = if_else(.data[[f1]] == -1, info1$Bajo, info1$Alto),
      Nivel_linea_real = if_else(.data[[f2]] == -1, info2$Bajo, info2$Alto)
    ) %>%
    group_by(Nivel_x, Nivel_linea, Nivel_x_real, Nivel_linea_real) %>%
    summarise(Media_Rendimiento = mean(Rendimiento, na.rm = TRUE), .groups = "drop") %>%
    mutate(
      Tooltip = paste0(
        f1, " = ", Nivel_x, " (", Nivel_x_real, ")",
        "<br>", f2, " = ", Nivel_linea, " (", Nivel_linea_real, ")",
        "<br>Media de rendimiento: ", round(Media_Rendimiento, 3)
      )
    )

  p <- ggplot(aux, aes(x = Nivel_x, y = Media_Rendimiento, group = Nivel_linea, linetype = Nivel_linea, text = Tooltip)) +
    geom_line() +
    geom_point(size = 2.8) +
    labs(
      title = paste("Interacción", par, "-", nombre),
      x = paste(f1, "-", info1$Nombre),
      y = "Media del rendimiento",
      linetype = paste(f2, "-", info2$Nombre)
    ) +
    theme_reporte()

  plotly::ggplotly(p, tooltip = "text")
}

for (par in interacciones_top) {
  print(grafico_interaccion(completo, par, "Diseño completo"))
}

14 Mejores combinaciones observadas

mejores_combinaciones <- completo %>%
  arrange(desc(Rendimiento)) %>%
  select(Corrida, Fraccion, Yates, A, B, C, D, E, Rendimiento) %>%
  slice_head(n = 10)

DT::datatable(mejores_combinaciones, caption = "Diez mejores combinaciones observadas", options = list(pageLength = 10, scrollX = TRUE), rownames = FALSE)

15 Comparación entre fracciones y diseño completo

Esta sección compara si la fracción principal y la fracción complementaria detectan los mismos efectos principales que el diseño completo.

comparacion_efectos_principales <- bind_rows(
  efectos_principal %>% mutate(Modelo_Corto = "Principal"),
  efectos_complementaria %>% mutate(Modelo_Corto = "Complementaria"),
  efectos_completo_main %>% mutate(Modelo_Corto = "Completo_main")
) %>%
  filter(!str_detect(term, ":")) %>%
  select(Modelo_Corto, term, Efecto, p.value, Significativo_5pct) %>%
  pivot_wider(
    names_from = Modelo_Corto,
    values_from = c(Efecto, p.value, Significativo_5pct)
  ) %>%
  mutate(
    Dif_Principal_vs_Completo = Efecto_Principal - Efecto_Completo_main,
    Dif_Complementaria_vs_Completo = Efecto_Complementaria - Efecto_Completo_main,
    Signo_Principal_igual_Completo = sign(Efecto_Principal) == sign(Efecto_Completo_main),
    Signo_Complementaria_igual_Completo = sign(Efecto_Complementaria) == sign(Efecto_Completo_main),
    Dif_Rel_Principal = abs(Dif_Principal_vs_Completo) / (abs(Efecto_Completo_main) + 1e-9),
    Dif_Rel_Complementaria = abs(Dif_Complementaria_vs_Completo) / (abs(Efecto_Completo_main) + 1e-9)
  )

DT::datatable(redondear_numericas(comparacion_efectos_principales, 4), caption = "Comparación de efectos principales", options = list(scrollX = TRUE), rownames = FALSE)
plot_comparacion <- comparacion_efectos_principales %>%
  select(term, Efecto_Principal, Efecto_Complementaria, Efecto_Completo_main) %>%
  pivot_longer(cols = starts_with("Efecto"), names_to = "Modelo", values_to = "Efecto") %>%
  mutate(
    Modelo = case_when(
      Modelo == "Efecto_Principal" ~ "Fracción principal",
      Modelo == "Efecto_Complementaria" ~ "Fracción complementaria",
      Modelo == "Efecto_Completo_main" ~ "Diseño completo",
      TRUE ~ Modelo
    ),
    Tooltip = paste0("Modelo: ", Modelo, "<br>Factor: ", term, "<br>Efecto: ", round(Efecto, 4))
  )

p_comp <- ggplot(plot_comparacion, aes(x = term, y = Efecto, group = Modelo, linetype = Modelo, text = Tooltip)) +
  geom_hline(yintercept = 0, linetype = "dashed") +
  geom_line() +
  geom_point(size = 2.8) +
  labs(title = "Comparación interactiva de efectos principales", x = "Factor", y = "Efecto estimado") +
  theme_reporte()

plotly::ggplotly(p_comp, tooltip = "text")

16 Criterios de decisión sobre el fraccionamiento

top_n <- 3

top_principal <- efectos_principal %>%
  filter(!str_detect(term, ":")) %>%
  arrange(desc(Abs_Efecto)) %>%
  slice_head(n = top_n) %>%
  pull(term)

top_complementaria <- efectos_complementaria %>%
  filter(!str_detect(term, ":")) %>%
  arrange(desc(Abs_Efecto)) %>%
  slice_head(n = top_n) %>%
  pull(term)

top_completo <- efectos_completo_main %>%
  filter(!str_detect(term, ":")) %>%
  arrange(desc(Abs_Efecto)) %>%
  slice_head(n = top_n) %>%
  pull(term)

coincidencia_top_principal <- length(intersect(top_principal, top_completo)) / top_n
coincidencia_top_complementaria <- length(intersect(top_complementaria, top_completo)) / top_n

signos_principal <- mean(comparacion_efectos_principales$Signo_Principal_igual_Completo, na.rm = TRUE)
signos_complementaria <- mean(comparacion_efectos_principales$Signo_Complementaria_igual_Completo, na.rm = TRUE)

resumen_decision <- tibble(
  Criterio = c(
    "Coincidencia top 3: fracción principal vs completo",
    "Coincidencia top 3: fracción complementaria vs completo",
    "Coincidencia de signos: fracción principal vs completo",
    "Coincidencia de signos: fracción complementaria vs completo"
  ),
  Valor = c(
    coincidencia_top_principal,
    coincidencia_top_complementaria,
    signos_principal,
    signos_complementaria
  )
)

DT::datatable(redondear_numericas(resumen_decision, 4), caption = "Criterios cuantitativos para evaluar el fraccionamiento", rownames = FALSE)
cat("Top", top_n, "factores en fracción principal:", paste(top_principal, collapse = ", "), "\n")
## Top 3 factores en fracción principal: B, A, C
cat("Top", top_n, "factores en fracción complementaria:", paste(top_complementaria, collapse = ", "), "\n")
## Top 3 factores en fracción complementaria: B, A, C
cat("Top", top_n, "factores en diseño completo:", paste(top_completo, collapse = ", "), "\n")
## Top 3 factores en diseño completo: B, A, C

17 Interpretación estadística y técnica

Con base en los resultados del análisis, se deben revisar estos puntos:

  1. Factores dominantes: si la fracción principal, la fracción complementaria y el diseño completo identifican los mismos factores principales dominantes, el fraccionamiento funciona bien como estrategia de cribado.
  2. Signo de los efectos: si los signos coinciden, la dirección del efecto es estable. Esto permite decidir si conviene usar el nivel bajo o alto de cada factor.
  3. Magnitud relativa: si las diferencias relativas frente al diseño completo son pequeñas para los factores importantes, la fracción principal conserva la información relevante.
  4. Interacciones de dos factores: el diseño completo permite verificar interacciones. Si aparece una interacción importante, la fracción principal puede no ser suficiente para explicar completamente el proceso, aunque sí puede servir para detectar los factores principales.
  5. Supuestos: si el modelo completo con interacciones mejora la normalidad y el ajuste, esto sugiere que parte de la variabilidad que parecía error en los modelos fraccionados en realidad correspondía a interacciones no incluidas.

18 Conclusión automática y mejor tratamiento

mejores_niveles <- efectos_completo_main %>%
  filter(!str_detect(term, ":")) %>%
  transmute(
    Factor = term,
    Efecto = Efecto,
    Nivel_Recomendado_Codificado = if_else(Efecto >= 0, "+1", "-1")
  ) %>%
  left_join(factor_info, by = "Factor") %>%
  mutate(
    Nivel_Recomendado_Real = if_else(Nivel_Recomendado_Codificado == "+1", Alto, Bajo)
  ) %>%
  select(Factor, Nombre, Efecto, Nivel_Recomendado_Codificado, Nivel_Recomendado_Real)

DT::datatable(redondear_numericas(mejores_niveles, 4), caption = "Niveles recomendados según efectos principales del diseño completo", rownames = FALSE)
factores_importantes <- efectos_completo_2fi %>%
  filter(Significativo_5pct == "Sí") %>%
  arrange(desc(Abs_t)) %>%
  pull(term)

cat("\n\n**Conclusión:**\n\n")

Conclusión:

if (coincidencia_top_principal == 1 && signos_principal == 1) {
  cat("La fracción principal reproduce correctamente los factores principales dominantes del diseño completo. Por tanto, como estrategia de cribado, el fraccionamiento es adecuado para identificar los factores con mayor efecto sobre el rendimiento.\n\n")
} else {
  cat("La fracción principal no reproduce completamente la jerarquía o los signos de los efectos principales del diseño completo. En este caso, se recomienda usar el diseño completo antes de tomar una decisión final.\n\n")
}

La fracción principal reproduce correctamente los factores principales dominantes del diseño completo. Por tanto, como estrategia de cribado, el fraccionamiento es adecuado para identificar los factores con mayor efecto sobre el rendimiento.

if (any(str_detect(factores_importantes, ":"))) {
  cat("Sin embargo, el diseño completo detecta al menos una interacción de dos factores relevante. Esto significa que el diseño fraccionado puede servir para una primera etapa de selección, pero el diseño completo aporta información adicional para optimizar el proceso.\n\n")
} else {
  cat("No se detectan interacciones de dos factores relevantes al 5% en el modelo completo. En ese escenario, la fracción principal sería suficiente para la toma de decisiones inicial.\n\n")
}

Sin embargo, el diseño completo detecta al menos una interacción de dos factores relevante. Esto significa que el diseño fraccionado puede servir para una primera etapa de selección, pero el diseño completo aporta información adicional para optimizar el proceso.

cat("Los efectos significativos o dominantes identificados en el diseño completo son: ", paste(factores_importantes, collapse = ", "), ".\n\n", sep = "")

Los efectos significativos o dominantes identificados en el diseño completo son: B, A, C, A:B, D:E.

cat("La recomendación operativa debe priorizar los niveles que aumentan el rendimiento: A, B y C tienden a ser los factores principales de mayor impacto positivo; D y E deben evaluarse con menor prioridad, salvo que aparezcan involucrados en interacciones relevantes.\n")

La recomendación operativa debe priorizar los niveles que aumentan el rendimiento: A, B y C tienden a ser los factores principales de mayor impacto positivo; D y E deben evaluarse con menor prioridad, salvo que aparezcan involucrados en interacciones relevantes.

19 Recomendaciones finales

  1. Usar la fracción principal como etapa inicial de cribado, porque reduce el número de corridas y permite detectar los factores principales dominantes.
  2. Confirmar la decisión con la fracción complementaria cuando el costo de equivocarse sea alto o cuando se sospechen interacciones.
  3. Utilizar el diseño completo si el Pareto del modelo completo muestra interacciones de dos factores relevantes.
  4. Seleccionar los niveles recomendados según los efectos positivos o negativos.
  5. Ejecutar corridas confirmatorias en la combinación óptima observada o predicha.
  6. Si se requiere optimización fina, continuar con un diseño de superficie de respuesta usando los factores más importantes.

Cierre del análisis: la decisión final debe basarse en la coincidencia de efectos dominantes, el signo de los efectos, la presencia de interacciones relevantes y la validación de supuestos. Si el diseño completo confirma efectos principales estables y no aparecen interacciones críticas, la fracción principal puede utilizarse como estrategia eficiente de cribado. Si aparecen interacciones significativas, el diseño completo ofrece una base más sólida para definir el tratamiento final.