[R-es] Marascuilo

Carlos Ortega co| @end|ng |rom qu@||tyexce||ence@e@
Jue Dic 4 09:22:46 CET 2025


Hola,

He preguntado a varias IAs y todas me han dado de primeras referencias
equivocadas (salvo Gemini 3), que de primeras me ha dicho que no está en R
de primeras.
Y tras indicar este problema, todas me han ofrecido implementaciones
directas...

(Emilio, a ver qué te dicen tus alumnos... :-) ).

Gracias,
Carlos Ortega
www.qualityexcellence.es

*_________ Gemini 3 _____________*

marascuilo_test <- function(counts, totals, alpha = 0.05) {
  # Calcular proporciones
  props <- counts / totals
  n_groups <- length(props)

  # Valor crítico de Chi-cuadrado
  chi_crit <- sqrt(qchisq(1 - alpha, df = n_groups - 1))

  # Crear combinaciones de pares
  pairs <- combn(1:n_groups, 2)
  results <- data.frame()

  for(i in 1:ncol(pairs)) {
    g1 <- pairs[1, i]
    g2 <- pairs[2, i]

    # Diferencia absoluta observada
    diff_obs <- abs(props[g1] - props[g2])

    # Rango crítico de Marascuilo
    # Fórmula: sqrt(chi_sq) * sqrt( p1(1-p1)/n1 + p2(1-p2)/n2 )
    se <- sqrt((props[g1] * (1 - props[g1]) / totals[g1]) +
               (props[g2] * (1 - props[g2]) / totals[g2]))
    critical_val <- chi_crit * se

    # ¿Es significativa la diferencia?
    sig <- diff_obs > critical_val

    results <- rbind(results, data.frame(
      Par = paste0("Grupo ", g1, " vs ", g2),
      Diferencia = round(diff_obs, 4),
      Valor_Critico = round(critical_val, 4),
      Significativo = sig
    ))
  }

  return(results)
}

# --- EJEMPLO DE USO ---
# Supongamos:
# Grupo 1: 30 éxitos de 100
# Grupo 2: 45 éxitos de 100
# Grupo 3: 20 éxitos de 100

exitos <- c(30, 45, 20)
total_muestras <- c(100, 100, 100)

print(marascuilo_test(exitos, total_muestras))

*____________ chtatGPT 5.1 ____________*

# marascuilo_test:
# Aplica el procedimiento de Marascuilo a una tabla de contingencia
# - 'tabla': data.frame o matrix con frecuencias.
#            Las columnas son los grupos a comparar.
#            La PRIMERA fila se considera la categoría de "éxito".
# - 'conf.level': nivel de confianza (por defecto 0.95)

marascuilo_test <- function(tabla, conf.level = 0.95) {
  tabla <- as.matrix(tabla)

  if (nrow(tabla) < 2) {
    stop("La tabla debe tener al menos 2 filas (éxito / no éxito, por
ejemplo).")
  }

  k <- ncol(tabla)
  grupos <- colnames(tabla)
  if (is.null(grupos)) grupos <- paste0("G", seq_len(k))

  # Totales por grupo y proporciones de la primera fila (p_i)
  n <- colSums(tabla)
  p <- tabla[1, ] / n

  # Constante chi-cuadrado
  df <- (nrow(tabla) - 1) * (ncol(tabla) - 1)
  chi_const <- sqrt(qchisq(conf.level, df = df))

  # Todas las combinaciones de pares
  comb <- t(combn(seq_len(k), 2))

  res <- data.frame(
    grupo1 = character(0),
    grupo2 = character(0),
    p1 = numeric(0),
    p2 = numeric(0),
    diff = numeric(0),
    crit_range = numeric(0),
    significativo = logical(0),
    stringsAsFactors = FALSE
  )

  for (r in seq_len(nrow(comb))) {
    i <- comb[r, 1]
    j <- comb[r, 2]

    diff_ij <- abs(p[i] - p[j])
    crit_ij <- chi_const * sqrt(
      p[i] * (1 - p[i]) / n[i] +
      p[j] * (1 - p[j]) / n[j]
    )

    res <- rbind(
      res,
      data.frame(
        grupo1 = grupos[i],
        grupo2 = grupos[j],
        p1 = p[i],
        p2 = p[j],
        diff = diff_ij,
        crit_range = crit_ij,
        significativo = diff_ij > crit_ij,
        stringsAsFactors = FALSE
      )
    )
  }

  # Ordenar por (diff - crit_range), de más “evidente” a menos
  res$exceso_diff <- res$diff - res$crit_range
  res[order(-res$exceso_diff), ]
}

#Ejemplo__________

tabla <- matrix(c(
  30, 50, 20,   # Y (éxito)
  70, 50, 80    # N (no éxito)
), nrow = 2, byrow = TRUE)

rownames(tabla) <- c("Y", "N")
colnames(tabla) <- c("A", "B", "C")

tabla

# Primero el chi-cuadrado global (opcional)
chisq.test(tabla, correct = FALSE)

# Luego Marascuilo
marascuilo_test(tabla, conf.level = 0.95)

*______________ Sonnet 4.5 ______________*

marascuilo_test <- function(x, n, alpha = 0.05) {
  # x: vector de éxitos
  # n: vector de tamaños de muestra

  k <- length(x)
  p <- x / n
  nombres <- names(x)
  if(is.null(nombres)) nombres <- paste0("Grupo", 1:k)

  # Valor crítico de chi-cuadrado
  chi_crit <- qchisq(1 - alpha, k - 1)

  # Crear matriz de comparaciones
  comparaciones <- data.frame()

  for(i in 1:(k-1)) {
    for(j in (i+1):k) {
      dif_abs <- abs(p[i] - p[j])
      valor_critico <- sqrt(chi_crit * (p[i]*(1-p[i])/n[i] +
p[j]*(1-p[j])/n[j]))
      significativo <- dif_abs > valor_critico

      comparaciones <- rbind(comparaciones,
                            data.frame(
                              Comparacion = paste(nombres[i], "vs",
nombres[j]),
                              Diferencia = dif_abs,
                              Valor_Critico = valor_critico,
                              Significativo = ifelse(significativo, "Sí",
"No")
                            ))
    }
  }

  return(list(
    proporciones = setNames(p, nombres),
    comparaciones = comparaciones,
    alpha = alpha
  ))
}

# Ejemplo de uso
exitos <- c(45, 38, 51)
totales <- c(100, 100, 100)
names(exitos) <- c("Tratamiento A", "Tratamiento B", "Tratamiento C")

resultado <- marascuilo_test(exitos, totales, alpha = 0.05)
print(resultado$proporciones)
print(resultado$comparaciones)


*__________________ Grok 4.1 ________________*

marascuilo_test <- function(tabla, alpha = 0.05, p.adjust = "fdr") {
  if (ncol(tabla) != 2) stop("La tabla debe ser r x 2 (grupos x
éxito/fracaso)")

  n <- rowSums(tabla)  # Totales por grupo
  p <- tabla[, 1] / n  # Proporciones
  nombres <- rownames(tabla)
  k <- length(p)

  # Todos los pares
  combinaciones <- combn(k, 2)
  num_pares <- ncol(combinaciones)

  # Diferencias absolutas
  diff <- abs(p[combinaciones[1, ]] - p[combinaciones[2, ]])

  # Valores críticos de Marascuilo
  chi_crit <- qchisq(1 - alpha, df = k - 1)
  crit <- sqrt(chi_crit) * sqrt(
    (p[combinaciones[1, ]] * (1 - p[combinaciones[1, ]])) /
n[combinaciones[1, ]] +
    (p[combinaciones[2, ]] * (1 - p[combinaciones[2, ]])) /
n[combinaciones[2, ]]
  )

  # p-valores aproximados (usando aproximación normal para referencia)
  se <- sqrt(
    (p[combinaciones[1, ]] * (1 - p[combinaciones[1, ]])) /
n[combinaciones[1, ]] +
    (p[combinaciones[2, ]] * (1 - p[combinaciones[2, ]])) /
n[combinaciones[2, ]]
  )
  z <- diff / se
  p.valor <- 2 * (1 - pnorm(z))

  # Ajuste de p-valores
  p.adj <- p.adjust(p.valor, method = p.adjust)

  # Data frame de resultados
  resultados <- data.frame(
    Grupo1 = nombres[combinaciones[1, ]],
    Grupo2 = nombres[combinaciones[2, ]],
    p1 = p[combinaciones[1, ]],
    p2 = p[combinaciones[2, ]],
    Diferencia = diff,
    Valor_Critico = crit,
    p.valor = p.valor,
    p.ajustado = p.adj,
    Significativo = ifelse(diff > crit, "*** (basado en crit)",
ifelse(p.adj < 0.05, "* (basado en p.adj)", " "))
  )

  print(resultados)
  cat("\nNotas:\n- *** si diferencia > valor crítico (método Marascuilo
exacto)\n- * si p.ajustado < 0.05\n")
  cat("Método de ajuste p: ", p.adjust, "\n")
  cat("Asume muestras grandes (n*p y n*(1-p) > 5 por celda).\n")
}

# Ejemplo de uso
marascuilo_test(datos, alpha = 0.05, p.adjust = "fdr")

___________________________________________________




El jue, 4 dic 2025 a las 8:21, Emilio L. Cano (<emilopezcano using gmail.com>)
escribió:

> Hola,
>
> Pues no he encontrado nada, es una buena oportunidad para desarrollar un
> paquete para este test y su análisis. Acabo de proponerlo como proyecto de
> TFG a mis estudiantes :)
>
> Saludos,
> Emilio
>
>
>
>
> > El 4 dic 2025, a las 6:20, Amable Moreno <morenoamable6 using gmail.com>
> escribió:
> >
> > Estimados colegas
> > Quisiera  saber si hay alguna librería para  aplicar el test de
> Marascuilo
> > Desde ya muchas gracias
> >
> >       [[alternative HTML version deleted]]
> >
> > _______________________________________________
> > R-help-es mailing list
> > R-help-es using r-project.org
> > https://stat.ethz.ch/mailman/listinfo/r-help-es
>
> _______________________________________________
> R-help-es mailing list
> R-help-es using r-project.org
> https://stat.ethz.ch/mailman/listinfo/r-help-es
>


-- 
Saludos,
Carlos Ortega
www.qualityexcellence.es

	[[alternative HTML version deleted]]



Más información sobre la lista de distribución R-help-es