Módulo IV. Test no paramétricos y análisis de concordancia

Objetivo del módulo

Desarrollar herramientas estadísticas para comparar grupos cuando las condiciones de los métodos paramétricos no resultan adecuadas y evaluar el grado de concordancia entre diferentes criterios de clasificación, utilizando datos microbiológicos y manteniendo el punto de muestreo como eje de la interpretación.

En este módulo se estudiarán:

  • prueba U de Mann–Whitney para dos grupos independientes;
  • prueba de Wilcoxon de rangos con signo para datos relacionados;
  • diferencias entre muestras independientes y pareadas;
  • construcción matemática de rangos;
  • formulación de hipótesis;
  • estimadores de localización;
  • intervalos de confianza;
  • tamaños del efecto;
  • concordancia observada y esperada;
  • índice Kappa de Cohen;
  • incertidumbre del Kappa;
  • concordancia por punto;
  • interpretación estadística;
  • e interpretación microbiológica de cada resultado.

1. ¿Por qué utilizar métodos no paramétricos?

En los módulos anteriores estudiamos procedimientos como:

\[ t,\qquad ANOVA,\qquad \text{Pearson} \]

Estos procedimientos permiten realizar inferencia sobre determinados parámetros poblacionales y requieren condiciones relacionadas con:

  • independencia;
  • distribución;
  • estructura de los errores;
  • homogeneidad de varianzas;
  • linealidad, según el procedimiento.

Sin embargo, los resultados microbiológicos pueden presentar:

  • fuerte asimetría;
  • valores extremos;
  • colas largas;
  • tamaños de muestra pequeños;
  • diferencias de varios órdenes de magnitud;
  • distribuciones alejadas de la normalidad.

En estas situaciones los procedimientos basados en rangos constituyen una alternativa útil.


1.1 ¿Qué significa no paramétrico?

Un método no paramétrico no significa que no tenga supuestos.

Significa que la inferencia depende menos de una forma paramétrica específica de la distribución.

Muchos procedimientos transforman:

\[ x_1,x_2,\ldots,x_n \]

en:

\[ R_1,R_2,\ldots,R_n \]

donde:

\[ R_i \]

representa el rango o posición de la observación.


1.2 Del valor al rango

Supongamos:

\[ 20,\quad50,\quad10,\quad80,\quad30 \]

Al ordenar:

\[ 10<20<30<50<80 \]

obtenemos:

Valor Rango
10 1
20 2
30 3
50 4
80 5

1.3 ¿Qué ocurre con los empates?

Supongamos:

\[ 10,\quad20,\quad20,\quad40 \]

Las dos observaciones iguales ocuparían los rangos 2 y 3.

Por tanto se asigna:

\[ \frac{2+3}{2}=2.5 \]

a ambas observaciones.

Valor Rango
10 1
20 2.5
20 2.5
40 4

R realiza automáticamente este ajuste.


2. Esquema general del módulo

\[ \boxed{\text{Dos grupos independientes}} \]

\[ \Downarrow \]

\[ \boxed{\text{U de Mann–Whitney}} \]

\[ \Downarrow \]

\[ \boxed{\text{Dos mediciones relacionadas}} \]

\[ \Downarrow \]

\[ \boxed{\text{Wilcoxon de rangos con signo}} \]

\[ \Downarrow \]

\[ \boxed{\text{Dos clasificaciones de las mismas unidades}} \]

\[ \Downarrow \]

\[ \boxed{\text{Kappa de Cohen}} \]


2.1 Diferencia fundamental entre las técnicas

Técnica Estructura Pregunta
Mann–Whitney Dos grupos independientes ¿Los grupos presentan distinto comportamiento?
Wilcoxon signed-rank Dos mediciones relacionadas ¿Existe un cambio sistemático?
Kappa de Cohen Dos clasificaciones sobre las mismas observaciones ¿Qué tanto coinciden más allá del azar?

3. Preparación de la base real

Trabajaremos nuevamente con:

data/DATOS I- SEM 2026.xlsx
library(readxl)

datos <- read_excel(
  "DATOS I- SEM 2026.xlsx"
)

names(datos) <- c(
  "analisis",
  "punto",
  "resultado_nmp",
  "matriz",
  "fecha"
)

# Eliminar registros con punto incompleto
datos <- datos[
  !is.na(datos$punto) &
  trimws(datos$punto) != "PUNTO_",
]

# Convertir NMP a numérico
datos$resultado_nmp <- as.numeric(
  gsub(
    ",",
    ".",
    as.character(datos$resultado_nmp),
    fixed = TRUE
  )
)

# Fecha
datos$fecha <- as.Date(
  datos$fecha
)

# Escala log10
datos$log10_nmp <- ifelse(
  !is.na(datos$resultado_nmp) &
  is.finite(datos$resultado_nmp) &
  datos$resultado_nmp > 0,
  log10(
    datos$resultado_nmp
  ),
  NA_real_
)

# Mes
datos$mes_num <- as.integer(
  format(
    datos$fecha,
    "%m"
  )
)

datos$mes <- factor(
  datos$mes_num,
  levels = 1:12,
  labels = c(
    "Enero", "Febrero", "Marzo", "Abril",
    "Mayo", "Junio", "Julio", "Agosto",
    "Septiembre", "Octubre", "Noviembre", "Diciembre"
  )
)

# P90 global
P90_global <- as.numeric(
  quantile(
    datos$resultado_nmp,
    probs = 0.90,
    na.rm = TRUE
  )
)

datos$evento_alerta <- ifelse(
  datos$resultado_nmp > P90_global,
  "Alerta",
  "Sin alerta"
)

datos$evento_alerta <- factor(
  datos$evento_alerta,
  levels = c(
    "Alerta",
    "Sin alerta"
  )
)

# P90 específico por punto
datos$P90_punto <- ave(
  datos$resultado_nmp,
  datos$punto,
  FUN = function(x) {
    
    rep(
      as.numeric(
        quantile(
          x,
          probs = 0.90,
          na.rm = TRUE
        )
      ),
      length(x)
    )
  }
)

datos$evento_alerta_punto <- ifelse(
  datos$resultado_nmp > datos$P90_punto,
  "Alerta",
  "Sin alerta"
)

datos$evento_alerta_punto <- factor(
  datos$evento_alerta_punto,
  levels = c(
    "Alerta",
    "Sin alerta"
  )
)

puntos_mod4 <- sort(
  unique(
    datos$punto
  )
)

4. El punto de muestreo como eje del módulo

El punto será utilizado de tres formas.

En Mann–Whitney:

\[ \boxed{\text{compararemos dos puntos independientes}} \]

En Wilcoxon:

\[ \boxed{\text{compararemos los mismos puntos en dos periodos}} \]

En concordancia:

\[ \boxed{ \text{evaluaremos cómo dos criterios clasifican los resultados de los puntos} } \]


5. Prueba U de Mann–Whitney

La prueba U de Mann–Whitney permite comparar una variable cuantitativa entre dos grupos independientes.

También recibe el nombre:

\[ \boxed{ \text{Wilcoxon rank-sum test} } \]

No debe confundirse con:

\[ \boxed{ \text{Wilcoxon signed-rank test} } \]

utilizado para datos pareados.


5.1 Pregunta microbiológica

En nuestra base podemos estudiar:

¿Dos puntos de muestreo presentan el mismo comportamiento microbiológico o existen diferencias en la distribución de sus resultados?

Tenemos:

\[ Y= \log_{10}(\text{NMP/100 mL}) \]

y:

\[ X= \text{Punto} \]

con dos categorías.


5.2 ¿Cuándo utilizar Mann–Whitney?

Puede ser útil cuando:

  • existen dos grupos independientes;
  • la respuesta puede ordenarse;
  • existe fuerte asimetría;
  • hay valores extremos;
  • la comparación paramétrica de medias no resulta apropiada.

5.3 Supuestos

La prueba requiere principalmente:

  1. observaciones independientes entre grupos;
  2. variable al menos ordinal;
  3. posibilidad de ordenar los valores;
  4. para interpretarla específicamente como diferencia de localización, formas de distribución razonablemente semejantes.

Cuando las formas son diferentes, la interpretación debe plantearse en términos generales de:

\[ \boxed{\text{diferencias en distribuciones/rangos}} \]


5.4 Hipótesis

Una formulación general es:

\[ H_0: F_1(x)=F_2(x) \]

frente a:

\[ H_1: F_1(x)\neq F_2(x) \]

donde:

  • \(F_1\): distribución del punto 1;
  • \(F_2\): distribución del punto 2.

5.5 Selección de dos puntos reales

conteo_mw <- table(
  datos$punto
)

puntos_mw <- names(
  conteo_mw[
    conteo_mw >= 5
  ]
)

if (
  length(
    puntos_mw
  ) >= 2
) {
  
  puntos_mw <- puntos_mw[
    1:2
  ]
  
  datos_mw <- datos[
    datos$punto %in% puntos_mw &
    is.finite(
      datos$log10_nmp
    ),
    c(
      "punto",
      "fecha",
      "resultado_nmp",
      "log10_nmp"
    )
  ]
  
  datos_mw$punto <- droplevels(
    factor(
      datos_mw$punto,
      levels = puntos_mw
    )
  )
  
  knitr::kable(
    head(
      datos_mw,
      12
    ),
    digits = 3,
    caption = paste(
      "Ejemplo Mann–Whitney:",
      paste(
        puntos_mw,
        collapse = " versus "
      )
    )
  )
  
} else {
  
  datos_mw <- NULL
  
  cat(
    "No existen dos puntos con suficientes observaciones."
  )
}
Ejemplo Mann–Whitney: PUNTO_11 versus PUNTO_16
punto fecha resultado_nmp log10_nmp
PUNTO_11 2026-05-06 3500.0 3.544
PUNTO_16 2026-05-06 230.0 2.362
PUNTO_11 2026-01-29 8164.0 3.912
PUNTO_16 2026-01-29 1935.0 3.287
PUNTO_11 2026-02-10 3448.0 3.538
PUNTO_16 2026-02-10 5172.0 3.714
PUNTO_11 2026-03-03 8664.0 3.938
PUNTO_11 2026-03-03 866.4 2.938
PUNTO_16 2026-03-03 360.9 2.557
PUNTO_16 2026-03-03 3609.0 3.557
PUNTO_11 2026-03-24 4352.0 3.639
PUNTO_11 2026-03-24 435.2 2.639

5.6 Resumen descriptivo de los dos puntos

if (
  !is.null(
    datos_mw
  )
) {
  
  resumen_mw <- do.call(
    rbind,
    lapply(
      split(
        datos_mw$log10_nmp,
        datos_mw$punto
      ),
      function(x) {
        
        x <- x[
          is.finite(x)
        ]
        
        data.frame(
          N = length(x),
          Media = mean(x),
          Mediana = median(x),
          Q1 = as.numeric(
            quantile(
              x,
              0.25
            )
          ),
          Q3 = as.numeric(
            quantile(
              x,
              0.75
            )
          ),
          IQR = IQR(x)
        )
      }
    )
  )
  
  resumen_mw$Punto <- rownames(
    resumen_mw
  )
  
  rownames(
    resumen_mw
  ) <- NULL
  
  resumen_mw <- resumen_mw[
    ,
    c(
      "Punto",
      "N",
      "Media",
      "Mediana",
      "Q1",
      "Q3",
      "IQR"
    )
  ]
  
  knitr::kable(
    resumen_mw,
    digits = 3,
    caption = "Resumen descriptivo de los puntos"
  )
}
Resumen descriptivo de los puntos
Punto N Media Mediana Q1 Q3 IQR
PUNTO_11 21 2.872 3.030 2.184 3.203 1.019
PUNTO_16 21 2.697 2.613 2.354 3.287 0.933

5.7 Interpretación microbiológica descriptiva

Antes de realizar la prueba debemos identificar:

  • cuál punto presenta mayor mediana;
  • cuál presenta mayor IQR;
  • si existe diferente dispersión;
  • si aparecen observaciones elevadas;
  • si las formas de las distribuciones son semejantes.

Una mediana superior indica que el punto tiende a presentar resultados microbiológicos más elevados.


5.8 Boxplot

if (
  !is.null(
    datos_mw
  )
) {
  
  boxplot(
    log10_nmp ~ punto,
    data = datos_mw,
    col = "#edf8f7",
    border = "#083d5c",
    xlab = "Punto de muestreo",
    ylab = expression(
      log[10]*"(NMP/100 mL)"
    ),
    main = "Comparación microbiológica entre dos puntos"
  )
  
  stripchart(
    log10_nmp ~ punto,
    data = datos_mw,
    vertical = TRUE,
    method = "jitter",
    add = TRUE,
    pch = 19,
    cex = 0.65,
    col = "#1596a5"
  )
}


5.9 Matemática de Mann–Whitney

Supongamos:

\[ A: a_1,\ldots,a_{n_1} \]

y:

\[ B: b_1,\ldots,b_{n_2} \]

Se combinan las:

\[ n_1+n_2 \]

observaciones y se ordenan.

A cada resultado se le asigna un rango:

\[ R_i \]


5.10 Ejemplo manual con cinco observaciones por punto

if (
  !is.null(
    datos_mw
  )
) {
  
  grupo1_mw <- datos_mw$log10_nmp[
    datos_mw$punto ==
    puntos_mw[1]
  ]
  
  grupo2_mw <- datos_mw$log10_nmp[
    datos_mw$punto ==
    puntos_mw[2]
  ]
  
  grupo1_5 <- head(
    grupo1_mw,
    5
  )
  
  grupo2_5 <- head(
    grupo2_mw,
    5
  )
  
  ejemplo_manual_mw <- data.frame(
    Valor = c(
      grupo1_5,
      grupo2_5
    ),
    Grupo = factor(
      c(
        rep(
          puntos_mw[1],
          length(
            grupo1_5
          )
        ),
        rep(
          puntos_mw[2],
          length(
            grupo2_5
          )
        )
      ),
      levels = puntos_mw
    )
  )
  
  ejemplo_manual_mw$Rango <- rank(
    ejemplo_manual_mw$Valor,
    ties.method = "average"
  )
  
  ejemplo_manual_mw <- ejemplo_manual_mw[
    order(
      ejemplo_manual_mw$Valor
    ),
  ]
  
  knitr::kable(
    ejemplo_manual_mw,
    digits = 3,
    caption = "Asignación de rangos"
  )
}
Asignación de rangos
Valor Grupo Rango
6 2.362 PUNTO_16 1
9 2.557 PUNTO_16 2
5 2.938 PUNTO_11 3
7 3.287 PUNTO_16 4
3 3.538 PUNTO_11 5
1 3.544 PUNTO_11 6
10 3.557 PUNTO_16 7
8 3.714 PUNTO_16 8
2 3.912 PUNTO_11 9
4 3.938 PUNTO_11 10

5.11 Suma de rangos

Para el grupo 1:

\[ R_1 = \sum R_i \]

Para el grupo 2:

\[ R_2 = \sum R_i \]

if (
  exists(
    "ejemplo_manual_mw"
  )
) {
  
  suma_rangos_mw <- tapply(
    ejemplo_manual_mw$Rango,
    ejemplo_manual_mw$Grupo,
    sum
  )
  
  suma_rangos_mw
}
## PUNTO_11 PUNTO_16 
##       33       22

5.12 Estadístico U

\[ U_1 = R_1 - \frac{ n_1(n_1+1) }{ 2 } \]

\[ U_2 = R_2 - \frac{ n_2(n_2+1) }{ 2 } \]

y:

\[ U_1+U_2 = n_1n_2 \]


5.13 Cálculo manual

if (
  exists(
    "ejemplo_manual_mw"
  )
) {
  
  n1_mw <- sum(
    ejemplo_manual_mw$Grupo ==
    puntos_mw[1]
  )
  
  n2_mw <- sum(
    ejemplo_manual_mw$Grupo ==
    puntos_mw[2]
  )
  
  R1_mw <- sum(
    ejemplo_manual_mw$Rango[
      ejemplo_manual_mw$Grupo ==
      puntos_mw[1]
    ]
  )
  
  R2_mw <- sum(
    ejemplo_manual_mw$Rango[
      ejemplo_manual_mw$Grupo ==
      puntos_mw[2]
    ]
  )
  
  U1_mw <- R1_mw -
    n1_mw *
    (
      n1_mw + 1
    ) / 2
  
  U2_mw <- R2_mw -
    n2_mw *
    (
      n2_mw + 1
    ) / 2
  
  tabla_u_mw <- data.frame(
    Estadistico = c(
      "R1",
      "R2",
      "U1",
      "U2"
    ),
    Valor = c(
      R1_mw,
      R2_mw,
      U1_mw,
      U2_mw
    )
  )
  
  knitr::kable(
    tabla_u_mw,
    digits = 3,
    caption = "Cálculo manual del estadístico U"
  )
}
Cálculo manual del estadístico U
Estadistico Valor
R1 33
R2 22
U1 18
U2 7

5.14 ¿Qué representa U?

El estadístico U está relacionado con la cantidad de veces que los valores de un grupo tienden a superar a los del otro.

Si las observaciones de ambos puntos se mezclan considerablemente en el ordenamiento:

\[ U \]

no mostrará una separación pronunciada.

Si un grupo tiende a concentrar rangos superiores, existe mayor evidencia de diferencia.


5.15 Mann–Whitney con todos los datos

Importante en R: cuando utilizamos la sintaxis de fórmula

respuesta ~ grupo

no debemos incluir el argumento paired.

La estructura de fórmula utilizada aquí corresponde automáticamente a dos grupos independientes.

if (
  !is.null(
    datos_mw
  ) &&
  nlevels(
    droplevels(
      datos_mw$punto
    )
  ) == 2
) {
  
  prueba_mw <- wilcox.test(
    log10_nmp ~ punto,
    data = datos_mw,
    exact = FALSE,
    conf.int = TRUE,
    conf.level = 0.95
  )
  
  prueba_mw
  
} else {
  
  prueba_mw <- NULL
  
  cat(
    "La prueba Mann–Whitney requiere exactamente dos grupos con observaciones válidas."
  )
}
## 
##  Wilcoxon rank sum test with continuity correction
## 
## data:  log10_nmp by punto
## W = 249, p-value = 0.4812
## alternative hypothesis: true location shift is not equal to 0
## 95 percent confidence interval:
##  -0.3540329  0.6940347
## sample estimates:
## difference in location 
##              0.2573363

5.16 ¿Por qué R reporta W?

R utiliza:

wilcox.test()

y reporta un estadístico denominado:

\[ W \]

basado en suma de rangos.

Dependiendo de la convención, puede relacionarse con U mediante:

\[ U = W- \frac{ n_1(n_1+1) }{ 2 } \]

La inferencia es equivalente.


5.17 Estimador de Hodges–Lehmann

Con:

conf.int = TRUE

R proporciona, cuando es posible, un estimador robusto del desplazamiento entre las distribuciones.

Este estimador no corresponde necesariamente a:

\[ \bar X_1-\bar X_2 \]

ni simplemente a:

\[ \widetilde X_1-\widetilde X_2 \]

Representa una estimación basada en diferencias entre observaciones.


5.18 Interpretación estadística

Si:

\[ p<0.05 \]

existe evidencia de diferencias entre los rangos/distribuciones de los puntos.

Si:

\[ p\geq0.05 \]

no existe evidencia suficiente para concluir que difieran.


5.19 Interpretación microbiológica

Un resultado significativo indica que ambos puntos no presentan el mismo perfil microbiológico.

Uno de ellos tiende a ocupar posiciones superiores o inferiores en la distribución de resultados.

Esto debe complementarse con:

  • mediana;
  • IQR;
  • resultados extremos;
  • comportamiento temporal.

5.20 Tamaño del efecto: correlación biserial de rangos

Podemos calcular:

\[ r_{rb} = \frac{ 2U_1 }{ n_1n_2 } - 1 \]

donde:

  • \(r_{rb}\): correlación biserial de rangos;
  • \(U_1\): estadístico U del grupo de referencia;
  • \(n_1,n_2\): tamaños muestrales.

5.21 Cálculo del tamaño del efecto

if (
  !is.null(
    datos_mw
  )
) {
  
  valores_mw <- datos_mw$log10_nmp
  grupos_mw <- datos_mw$punto
  
  rangos_total_mw <- rank(
    valores_mw,
    ties.method = "average"
  )
  
  n1_total_mw <- sum(
    grupos_mw ==
    puntos_mw[1]
  )
  
  n2_total_mw <- sum(
    grupos_mw ==
    puntos_mw[2]
  )
  
  R1_total_mw <- sum(
    rangos_total_mw[
      grupos_mw ==
      puntos_mw[1]
    ]
  )
  
  U1_total_mw <- R1_total_mw -
    n1_total_mw *
    (
      n1_total_mw + 1
    ) / 2
  
  r_rb_mw <- (
    2 *
    U1_total_mw /
    (
      n1_total_mw *
      n2_total_mw
    )
  ) - 1
  
  r_rb_mw
}
## [1] 0.1292517

5.22 Magnitud orientativa

\(|r_{rb}|\) Interpretación aproximada
0.10 Pequeña
0.30 Moderada
0.50 o superior Grande

Estas referencias son orientativas.


5.23 Interpretación integrada de Mann–Whitney

La conclusión debe combinar:

\[ \boxed{ \text{Boxplot} + \text{Medianas} + IQR } \]

\[ + \]

\[ \boxed{ U/W + p + IC + r_{rb} } \]

Interpretación microbiológica

Los resultados permiten determinar si dos puntos presentan perfiles microbiológicos semejantes o si uno de ellos tiende a registrar valores sistemáticamente superiores. Esta diferencia debe interpretarse en conjunto con la variabilidad interna y el comportamiento temporal de cada punto.


5.24 Ruta de Mann–Whitney

\[ \boxed{\text{Dos puntos independientes}} \]

\[ \Downarrow \]

\[ \boxed{\text{Resumen + Boxplot}} \]

\[ \Downarrow \]

\[ \boxed{\text{Ordenar resultados}} \]

\[ \Downarrow \]

\[ \boxed{\text{Asignar rangos}} \]

\[ \Downarrow \]

\[ \boxed{R_1,R_2} \]

\[ \Downarrow \]

\[ \boxed{U_1,U_2} \]

\[ \Downarrow \]

\[ \boxed{p+\text{IC}+r_{rb}} \]

\[ \Downarrow \]

\[ \boxed{\text{Interpretación microbiológica}} \]


6. Prueba de Wilcoxon de rangos con signo

El test de Wilcoxon de rangos con signo se utiliza para dos mediciones relacionadas.

La unidad observacional debe mantenerse.

En nuestro contexto podemos utilizar:

\[ \text{Punto }j \]

medido en:

\[ \text{Periodo 1} \]

y nuevamente en:

\[ \text{Periodo 2} \]


6.1 Diferencia con Mann–Whitney

Mann–Whitney:

\[ \boxed{\text{dos grupos independientes}} \]

Wilcoxon signed-rank:

\[ \boxed{\text{dos mediciones pareadas}} \]


6.2 Aplicación con nuestra base

Para evitar que un punto con mayor número de registros tenga más peso, resumiremos cada:

\[ \text{Punto}\times\text{Mes} \]

mediante:

\[ \widetilde X_{jm} \]

la mediana en escala log10.


6.3 Mediana mensual por punto

datos_wilcox_base <- datos[
  is.finite(
    datos$log10_nmp
  ) &
  !is.na(
    datos$mes_num
  ),
]

medianas_mes_punto <- aggregate(
  log10_nmp ~ punto + mes_num,
  data = datos_wilcox_base,
  FUN = median
)

names(
  medianas_mes_punto
)[3] <- "mediana_log10"

knitr::kable(
  head(
    medianas_mes_punto,
    15
  ),
  digits = 3,
  caption = "Mediana mensual por punto"
)
Mediana mensual por punto
punto mes_num mediana_log10
PUNTO_11 1 3.912
PUNTO_16 1 3.287
PUNTO_17 1 3.368
PUNTO_18 1 3.304
PUNTO_19 1 5.158
PUNTO_20 1 4.638
PUNTO_21 1 4.501
PUNTO_23 1 5.639
PUNTO_4 1 5.995
PUNTO_5 1 7.639
PUNTO_6 1 6.763
PUNTO_7 1 4.934
PUNTO_8 1 6.034
PUNTO_9 1 5.946
PUNTO_11 2 3.538

6.4 Selección de dos meses con puntos comunes

meses_disponibles_w <- sort(
  unique(
    medianas_mes_punto$mes_num
  )
)

mejor_par_w <- NULL
max_comunes_w <- 0

if (
  length(
    meses_disponibles_w
  ) >= 2
) {
  
  pares_w <- combn(
    meses_disponibles_w,
    2
  )
  
  for (
    j in seq_len(
      ncol(
        pares_w
      )
    )
  ) {
    
    m1 <- pares_w[
      1,
      j
    ]
    
    m2 <- pares_w[
      2,
      j
    ]
    
    puntos_m1 <- medianas_mes_punto$punto[
      medianas_mes_punto$mes_num ==
      m1
    ]
    
    puntos_m2 <- medianas_mes_punto$punto[
      medianas_mes_punto$mes_num ==
      m2
    ]
    
    n_comunes <- length(
      intersect(
        puntos_m1,
        puntos_m2
      )
    )
    
    if (
      n_comunes >
      max_comunes_w
    ) {
      
      max_comunes_w <- n_comunes
      
      mejor_par_w <- c(
        m1,
        m2
      )
    }
  }
}

6.5 Construcción de los pares

if (
  !is.null(
    mejor_par_w
  ) &&
  max_comunes_w >= 3
) {
  
  periodo1_w <- medianas_mes_punto[
    medianas_mes_punto$mes_num ==
    mejor_par_w[1],
    c(
      "punto",
      "mediana_log10"
    )
  ]
  
  periodo2_w <- medianas_mes_punto[
    medianas_mes_punto$mes_num ==
    mejor_par_w[2],
    c(
      "punto",
      "mediana_log10"
    )
  ]
  
  names(
    periodo1_w
  )[2] <- "Periodo_1"
  
  names(
    periodo2_w
  )[2] <- "Periodo_2"
  
  datos_pareados_w <- merge(
    periodo1_w,
    periodo2_w,
    by = "punto"
  )
  
  datos_pareados_w$Diferencia <- (
    datos_pareados_w$Periodo_2 -
    datos_pareados_w$Periodo_1
  )
  
  knitr::kable(
    datos_pareados_w,
    digits = 3,
    caption = paste(
      "Comparación pareada entre los meses",
      mejor_par_w[1],
      "y",
      mejor_par_w[2]
    )
  )
  
} else {
  
  datos_pareados_w <- NULL
  
  cat(
    "No existen suficientes puntos comunes entre dos periodos."
  )
}
Comparación pareada entre los meses 5 y 6
punto Periodo_1 Periodo_2 Diferencia
PUNTO_11 3.056 2.430 -0.626
PUNTO_16 2.362 2.062 -0.300
PUNTO_17 2.688 2.292 -0.396
PUNTO_18 3.114 2.318 -0.796
PUNTO_19 5.538 4.013 -1.525
PUNTO_20 3.362 4.058 0.696
PUNTO_21 3.852 2.600 -1.253
PUNTO_23 3.362 4.151 0.789
PUNTO_24 5.845 3.382 -2.463
PUNTO_25 4.380 3.988 -0.392
PUNTO_26 4.380 4.101 -0.279
PUNTO_5 7.041 5.229 -1.812
PUNTO_6 6.664 4.539 -2.125
PUNTO_7 4.362 3.944 -0.418
PUNTO_8 5.362 4.650 -0.712
PUNTO_9 5.768 3.762 -2.006

6.6 ¿Qué significa estar pareado?

Para cada punto \(j\):

\[ (X_{j1},X_{j2}) \]

corresponde a la misma unidad observada en dos momentos.

La variable fundamental es:

\[ D_j = X_{j2}-X_{j1} \]


6.7 Hipótesis

Una formulación general es:

\[ H_0: \text{la distribución de las diferencias está centrada en 0} \]

frente a:

\[ H_1: \text{existe un desplazamiento distinto de 0} \]

Cuando la distribución de diferencias es aproximadamente simétrica:

\[ H_0: \widetilde D=0 \]


6.8 Supuestos

La prueba requiere:

  • pareamiento correcto;
  • independencia entre pares;
  • respuesta al menos ordinal;
  • simetría razonable de las diferencias para la interpretación clásica de desplazamiento.

6.9 Gráfico pareado

if (
  !is.null(
    datos_pareados_w
  )
) {
  
  rango_y_w <- range(
    c(
      datos_pareados_w$Periodo_1,
      datos_pareados_w$Periodo_2
    ),
    na.rm = TRUE
  )
  
  plot(
    NA,
    xlim = c(
      0.8,
      2.2
    ),
    ylim = rango_y_w,
    xaxt = "n",
    xlab = "Periodo",
    ylab = expression(
      "Mediana de " *
      log[10] *
      "(NMP/100 mL)"
    ),
    main = "Cambio de los mismos puntos entre periodos"
  )
  
  for (
    i in seq_len(
      nrow(
        datos_pareados_w
      )
    )
  ) {
    
    lines(
      c(
        1,
        2
      ),
      c(
        datos_pareados_w$Periodo_1[i],
        datos_pareados_w$Periodo_2[i]
      ),
      type = "b",
      pch = 19,
      col = "#1596a5"
    )
  }
  
  axis(
    1,
    at = 1:2,
    labels = c(
      paste0(
        "Mes ",
        mejor_par_w[1]
      ),
      paste0(
        "Mes ",
        mejor_par_w[2]
      )
    )
  )
}


6.10 Interpretación microbiológica

Cada línea corresponde al mismo punto.

Si la mayoría asciende:

\[ \text{Periodo 2} > \text{Periodo 1} \]

existe una señal descriptiva de incremento.

Si la mayoría desciende, ocurre lo contrario.


6.11 Diferencias pareadas

if (
  !is.null(
    datos_pareados_w
  )
) {
  
  knitr::kable(
    datos_pareados_w[
      ,
      c(
        "punto",
        "Periodo_1",
        "Periodo_2",
        "Diferencia"
      )
    ],
    digits = 3,
    caption = "Diferencias entre periodos por punto"
  )
}
Diferencias entre periodos por punto
punto Periodo_1 Periodo_2 Diferencia
PUNTO_11 3.056 2.430 -0.626
PUNTO_16 2.362 2.062 -0.300
PUNTO_17 2.688 2.292 -0.396
PUNTO_18 3.114 2.318 -0.796
PUNTO_19 5.538 4.013 -1.525
PUNTO_20 3.362 4.058 0.696
PUNTO_21 3.852 2.600 -1.253
PUNTO_23 3.362 4.151 0.789
PUNTO_24 5.845 3.382 -2.463
PUNTO_25 4.380 3.988 -0.392
PUNTO_26 4.380 4.101 -0.279
PUNTO_5 7.041 5.229 -1.812
PUNTO_6 6.664 4.539 -2.125
PUNTO_7 4.362 3.944 -0.418
PUNTO_8 5.362 4.650 -0.712
PUNTO_9 5.768 3.762 -2.006

6.12 Construcción matemática de los rangos con signo

Primero:

\[ D_i= Y_i-X_i \]

Se excluyen los casos:

\[ D_i=0 \]

Posteriormente calculamos:

\[ |D_i| \]

y asignamos rangos.

Finalmente recuperamos el signo de:

\[ D_i \]


6.13 Tabla de rangos con signo

if (
  !is.null(
    datos_pareados_w
  )
) {
  
  tabla_w <- datos_pareados_w[
    datos_pareados_w$Diferencia != 0,
  ]
  
  if (
    nrow(
      tabla_w
    ) > 0
  ) {
    
    tabla_w$Abs_Diferencia <- abs(
      tabla_w$Diferencia
    )
    
    tabla_w$Rango <- rank(
      tabla_w$Abs_Diferencia,
      ties.method = "average"
    )
    
    tabla_w$Signo <- ifelse(
      tabla_w$Diferencia > 0,
      "+",
      "-"
    )
    
    tabla_w$Rango_con_signo <- ifelse(
      tabla_w$Diferencia > 0,
      tabla_w$Rango,
      -tabla_w$Rango
    )
    
    knitr::kable(
      tabla_w[
        ,
        c(
          "punto",
          "Diferencia",
          "Abs_Diferencia",
          "Rango",
          "Signo",
          "Rango_con_signo"
        )
      ],
      digits = 3,
      caption = "Construcción de los rangos con signo"
    )
    
  } else {
    
    tabla_w <- NULL
    
    cat(
      "Todas las diferencias son iguales a cero."
    )
  }
}
Construcción de los rangos con signo
punto Diferencia Abs_Diferencia Rango Signo Rango_con_signo
PUNTO_11 -0.626 0.626 6 - -6
PUNTO_16 -0.300 0.300 2 - -2
PUNTO_17 -0.396 0.396 4 - -4
PUNTO_18 -0.796 0.796 10 - -10
PUNTO_19 -1.525 1.525 12 - -12
PUNTO_20 0.696 0.696 7 + 7
PUNTO_21 -1.253 1.253 11 - -11
PUNTO_23 0.789 0.789 9 + 9
PUNTO_24 -2.463 2.463 16 - -16
PUNTO_25 -0.392 0.392 3 - -3
PUNTO_26 -0.279 0.279 1 - -1
PUNTO_5 -1.812 1.812 13 - -13
PUNTO_6 -2.125 2.125 15 - -15
PUNTO_7 -0.418 0.418 5 - -5
PUNTO_8 -0.712 0.712 8 - -8
PUNTO_9 -2.006 2.006 14 - -14

6.14 Suma de rangos positivos y negativos

\[ W^+ = \sum_{D_i>0} R_i \]

\[ W^- = \sum_{D_i<0} R_i \]

if (
  exists(
    "tabla_w"
  ) &&
  !is.null(
    tabla_w
  )
) {
  
  W_positivo <- sum(
    tabla_w$Rango[
      tabla_w$Diferencia > 0
    ]
  )
  
  W_negativo <- sum(
    tabla_w$Rango[
      tabla_w$Diferencia < 0
    ]
  )
  
  data.frame(
    Estadistico = c(
      "W positivo",
      "W negativo"
    ),
    Valor = c(
      W_positivo,
      W_negativo
    )
  )
}
##   Estadistico Valor
## 1  W positivo    16
## 2  W negativo   120

6.15 Interpretación

Si:

\[ W^+ \gg W^- \]

predominan aumentos.

Si:

\[ W^- \gg W^+ \]

predominan disminuciones.


6.16 Wilcoxon pareado en R

Aquí sí podemos utilizar:

paired = TRUE

porque estamos utilizando la interfaz de dos vectores numéricos, no la interfaz de fórmula.

if (
  !is.null(
    datos_pareados_w
  ) &&
  nrow(
    datos_pareados_w
  ) >= 3 &&
  any(
    datos_pareados_w$Diferencia != 0
  )
) {
  
  prueba_wilcoxon <- suppressWarnings(
    wilcox.test(
      x = datos_pareados_w$Periodo_2,
      y = datos_pareados_w$Periodo_1,
      paired = TRUE,
      exact = FALSE,
      conf.int = TRUE,
      conf.level = 0.95
    )
  )
  
  prueba_wilcoxon
  
} else {
  
  prueba_wilcoxon <- NULL
  
  cat(
    "No existen suficientes pares con diferencias distintas de cero para ejecutar Wilcoxon."
  )
}
## 
##  Wilcoxon signed rank test with continuity correction
## 
## data:  datos_pareados_w$Periodo_2 and datos_pareados_w$Periodo_1
## V = 16, p-value = 0.007745
## alternative hypothesis: true location shift is not equal to 0
## 95 percent confidence interval:
##  -1.3815328 -0.3589934
## sample estimates:
## (pseudo)median 
##     -0.8225421

6.17 Estimador de Hodges–Lehmann

Cuando es posible, la prueba proporciona una estimación robusta del desplazamiento entre ambas condiciones.

Esto permite complementar:

\[ p \]

con información sobre:

\[ \boxed{\text{magnitud del cambio}} \]


6.18 Interpretación estadística

Si:

\[ p<0.05 \]

existe evidencia de un cambio sistemático entre los dos periodos.

Si:

\[ p\geq0.05 \]

no existe evidencia suficiente para afirmar que las diferencias estén desplazadas de cero.


6.19 Tamaño del efecto

Podemos utilizar:

\[ r_{rb} = \frac{ W^+-W^- }{ W^++W^- } \]


6.20 Cálculo

if (
  exists(
    "W_positivo"
  ) &&
  exists(
    "W_negativo"
  ) &&
  (
    W_positivo +
    W_negativo
  ) > 0
) {
  
  r_rb_wilcoxon <- (
    W_positivo -
    W_negativo
  ) /
  (
    W_positivo +
    W_negativo
  )
  
  r_rb_wilcoxon
}
## [1] -0.7647059

6.21 Interpretación microbiológica

Un resultado significativo indica que los puntos presentan un cambio sistemático entre ambos periodos.

Si:

\[ r_{rb}>0 \]

según la orientación utilizada, predominan incrementos hacia el segundo periodo.

Si:

\[ r_{rb}<0 \]

predominan reducciones.

La causa de esos cambios no puede determinarse únicamente mediante esta prueba.


6.22 ¿Por qué no tratar estos periodos como independientes?

Porque:

\[ \boxed{ \text{el mismo punto aparece en ambos periodos} } \]

Por ello existe una relación natural entre ambas mediciones.

El análisis debe aprovechar:

\[ D_i = Y_i-X_i \]

en lugar de ignorar el pareamiento.


6.23 Ruta de Wilcoxon

\[ \boxed{\text{Mismos puntos}} \]

\[ \Downarrow \]

\[ \boxed{\text{Dos periodos}} \]

\[ \Downarrow \]

\[ \boxed{D_i=Y_i-X_i} \]

\[ \Downarrow \]

\[ \boxed{|D_i|} \]

\[ \Downarrow \]

\[ \boxed{\text{Rangos}} \]

\[ \Downarrow \]

\[ \boxed{W^+,W^-} \]

\[ \Downarrow \]

\[ \boxed{p+\text{IC}+r_{rb}} \]

\[ \Downarrow \]

\[ \boxed{\text{Interpretación microbiológica}} \]


7. Análisis de concordancia

Hasta ahora estudiamos:

\[ \boxed{\text{diferencias}} \]

Ahora queremos estudiar:

\[ \boxed{\text{coincidencia}} \]

La pregunta será:

¿Dos criterios asignan la misma categoría a las mismas observaciones?


7.1 Asociación y concordancia son diferentes

Dos criterios pueden estar asociados y, sin embargo, no clasificar exactamente igual.

La concordancia requiere coincidencia de categorías.


7.2 Aplicación a nuestra base

Cada resultado tiene dos clasificaciones.

Criterio global

\[ X_i>P90_{\text{global}} \]

Criterio específico del punto

\[ X_i>P90_j \]

Podemos estudiar la concordancia entre:

\[ \boxed{\text{Alerta global}} \]

y:

\[ \boxed{\text{Alerta específica del punto}} \]


7.3 Precaución microbiológica

Estas clasificaciones no representan dos analistas independientes.

Representan dos criterios estadísticos de referencia.

Por ello Kappa se utiliza aquí para cuantificar:

\[ \boxed{ \text{concordancia entre dos reglas} } \]

No para demostrar validez normativa.


8. Tabla de concordancia

La estructura es:

Local: Alerta Local: Sin alerta
Global: Alerta \(a\) \(b\)
Global: Sin alerta \(c\) \(d\)

8.1 Tabla real

tabla_kappa <- table(
  Global = factor(
    datos$evento_alerta,
    levels = c(
      "Alerta",
      "Sin alerta"
    )
  ),
  Local = factor(
    datos$evento_alerta_punto,
    levels = c(
      "Alerta",
      "Sin alerta"
    )
  )
)

tabla_kappa
##             Local
## Global       Alerta Sin alerta
##   Alerta         11         20
##   Sin alerta     20        256

8.2 Interpretación microbiológica de las celdas

Global y local = Alerta

Resultado elevado frente a toda la base y también inusual para su punto.

Global = Alerta, local = Sin alerta

Elevado frente al conjunto general, pero relativamente habitual para ese punto.

Global = Sin alerta, local = Alerta

No es extremo globalmente, pero sí es inusual para el comportamiento propio del punto.

Ambos = Sin alerta

No supera ninguno de los dos criterios estadísticos.


9. Acuerdo observado

\[ P_o = \frac{ a+d }{ N } \]

N_kappa <- sum(
  tabla_kappa
)

Po <- sum(
  diag(
    tabla_kappa
  )
) /
N_kappa

Po
## [1] 0.8697068

9.1 Porcentaje de acuerdo

Po * 100
## [1] 86.97068

10. ¿Por qué no basta con el acuerdo observado?

Si la mayoría de los resultados pertenece a:

\[ \text{Sin alerta} \]

ambos criterios pueden coincidir frecuentemente simplemente porque esa categoría es dominante.

Por ello debemos estimar el acuerdo esperado.


11. Acuerdo esperado por azar

\[ P_e = \sum_{j=1}^{k} P_{Aj}P_{Bj} \]

Para dos categorías:

\[ P_e = P_{A1}P_{B1} + P_{A2}P_{B2} \]

proporcion_global_k <- prop.table(
  margin.table(
    tabla_kappa,
    1
  )
)

proporcion_local_k <- prop.table(
  margin.table(
    tabla_kappa,
    2
  )
)

Pe <- sum(
  proporcion_global_k *
  proporcion_local_k
)

Pe
## [1] 0.8184384

12. Índice Kappa de Cohen

\[ \kappa = \frac{ P_o-P_e }{ 1-P_e } \]

donde:

  • \(P_o\): acuerdo observado;
  • \(P_e\): acuerdo esperado;
  • \(\kappa\): acuerdo corregido por azar.

12.1 Cálculo manual

if (
  is.finite(
    Pe
  ) &&
  (
    1 -
    Pe
  ) > 0
) {
  
  kappa_mod4 <- (
    Po -
    Pe
  ) /
  (
    1 -
    Pe
  )
  
} else {
  
  kappa_mod4 <- NA_real_
}

kappa_mod4
## [1] 0.2823749

12.2 Resumen

resumen_kappa <- data.frame(
  Medida = c(
    "Acuerdo observado",
    "Acuerdo esperado",
    "Kappa de Cohen"
  ),
  Valor = c(
    Po,
    Pe,
    kappa_mod4
  )
)

knitr::kable(
  resumen_kappa,
  digits = 4,
  caption = "Medidas de concordancia"
)
Medidas de concordancia
Medida Valor
Acuerdo observado 0.8697
Acuerdo esperado 0.8184
Kappa de Cohen 0.2824

13. Interpretación orientativa de Kappa

\(\kappa\) Interpretación descriptiva
< 0 Inferior al azar
0.00–0.20 Ligero
0.21–0.40 Bajo
0.41–0.60 Moderado
0.61–0.80 Sustancial
0.81–1.00 Muy alto

Estos límites son orientativos y no deben utilizarse como fronteras absolutas.


13.1 Kappa y prevalencia

Kappa puede verse afectado por:

  • predominio de una categoría;
  • desequilibrio marginal;
  • tamaño muestral;
  • diferencias sistemáticas entre criterios.

Por ello siempre debe reportarse:

\[ \boxed{ \text{Tabla} + P_o + P_e + \kappa } \]


14. Intervalo de confianza de Kappa mediante bootstrap

Para expresar la incertidumbre utilizaremos remuestreo.


14.1 Función para Kappa

calcular_kappa <- function(a, b) {
  
  tabla <- table(
    factor(
      a,
      levels = c(
        "Alerta",
        "Sin alerta"
      )
    ),
    factor(
      b,
      levels = c(
        "Alerta",
        "Sin alerta"
      )
    )
  )
  
  N <- sum(
    tabla
  )
  
  if (
    N == 0
  ) {
    
    return(
      NA_real_
    )
  }
  
  Po_temp <- sum(
    diag(
      tabla
    )
  ) /
  N
  
  pa <- prop.table(
    margin.table(
      tabla,
      1
    )
  )
  
  pb <- prop.table(
    margin.table(
      tabla,
      2
    )
  )
  
  Pe_temp <- sum(
    pa *
    pb
  )
  
  if (
    !is.finite(
      Pe_temp
    ) ||
    (
      1 -
      Pe_temp
    ) <= 0
  ) {
    
    return(
      NA_real_
    )
  }
  
  (
    Po_temp -
    Pe_temp
  ) /
  (
    1 -
    Pe_temp
  )
}

14.2 Bootstrap

set.seed(
  123
)

B_kappa <- 1000

kappa_boot <- replicate(
  B_kappa,
  {
    
    indices <- sample(
      seq_len(
        nrow(
          datos
        )
      ),
      size = nrow(
        datos
      ),
      replace = TRUE
    )
    
    calcular_kappa(
      datos$evento_alerta[
        indices
      ],
      datos$evento_alerta_punto[
        indices
      ]
    )
  }
)

kappa_boot <- kappa_boot[
  is.finite(
    kappa_boot
  )
]

if (
  length(
    kappa_boot
  ) > 20
) {
  
  IC_kappa <- quantile(
    kappa_boot,
    probs = c(
      0.025,
      0.975
    ),
    na.rm = TRUE
  )
  
  IC_kappa
  
} else {
  
  IC_kappa <- c(
    NA_real_,
    NA_real_
  )
  
  cat(
    "No se obtuvieron suficientes remuestras válidas para estimar el intervalo de Kappa."
  )
}
##      2.5%     97.5% 
## 0.1175583 0.4470682

14.3 Interpretación del intervalo

Un intervalo estrecho indica mayor precisión.

Un intervalo amplio indica que la verdadera concordancia compatible con los datos puede encontrarse en un rango considerable.


15. Gráfico de concordancia

porcentaje_kappa <- prop.table(
  tabla_kappa
) * 100

barplot(
  porcentaje_kappa,
  beside = TRUE,
  col = c(
    "#1596a5",
    "#dcecef"
  ),
  border = NA,
  xlab = "Clasificación local",
  ylab = "Porcentaje total",
  main = "Concordancia entre criterios global y local"
)

legend(
  "topright",
  legend = rownames(
    porcentaje_kappa
  ),
  fill = c(
    "#1596a5",
    "#dcecef"
  ),
  border = NA,
  bty = "n",
  title = "Clasificación global"
)


16. Acuerdo por punto

Aunque Kappa global resume la base completa, también podemos identificar qué sucede en cada punto.

acuerdo_por_punto <- do.call(
  rbind,
  lapply(
    split(
      datos,
      datos$punto
    ),
    function(df) {
      
      validos <- !is.na(
        df$evento_alerta
      ) &
      !is.na(
        df$evento_alerta_punto
      )
      
      if (
        sum(
          validos
        ) > 0
      ) {
        
        acuerdo <- mean(
          as.character(
            df$evento_alerta[
              validos
            ]
          ) ==
          as.character(
            df$evento_alerta_punto[
              validos
            ]
          )
        )
        
      } else {
        
        acuerdo <- NA_real_
      }
      
      data.frame(
        N = sum(
          validos
        ),
        Acuerdo = acuerdo,
        Porcentaje =
          acuerdo * 100
      )
    }
  )
)

acuerdo_por_punto$Punto <- rownames(
  acuerdo_por_punto
)

rownames(
  acuerdo_por_punto
) <- NULL

acuerdo_por_punto <- acuerdo_por_punto[
  order(
    acuerdo_por_punto$Porcentaje,
    decreasing = TRUE,
    na.last = TRUE
  ),
]

knitr::kable(
  acuerdo_por_punto,
  digits = 2,
  caption = "Concordancia entre criterios por punto"
)
Concordancia entre criterios por punto
N Acuerdo Porcentaje Punto
15 21 1.00 100.00 PUNTO_7
17 22 0.95 95.45 PUNTO_9
2 21 0.95 95.24 PUNTO_16
5 22 0.91 90.91 PUNTO_19
8 22 0.91 90.91 PUNTO_23
10 11 0.91 90.91 PUNTO_25
11 11 0.91 90.91 PUNTO_26
1 21 0.90 90.48 PUNTO_11
3 21 0.90 90.48 PUNTO_17
4 21 0.90 90.48 PUNTO_18
6 21 0.90 90.48 PUNTO_20
7 21 0.90 90.48 PUNTO_21
9 7 0.86 85.71 PUNTO_24
12 6 0.83 83.33 PUNTO_4
16 20 0.70 70.00 PUNTO_8
14 20 0.65 65.00 PUNTO_6
13 19 0.63 63.16 PUNTO_5

16.1 Interpretación microbiológica por punto

Un porcentaje elevado indica que ambos criterios suelen producir la misma clasificación en esa ubicación.

Una concordancia menor indica que:

\[ P90_{\text{global}} \]

y:

\[ P90_j \]

están señalando aspectos distintos del comportamiento microbiológico.


17. Concordancia no significa validez

Incluso si:

\[ \kappa=1 \]

solo podemos afirmar:

\[ \boxed{ \text{los dos criterios coinciden perfectamente} } \]

No podemos afirmar:

\[ \boxed{ \text{los dos criterios son normativamente correctos} } \]

porque ambos P90 son criterios estadísticos de priorización.


18. Problema de prevalencia

Si casi todas las observaciones son:

\[ \text{Sin alerta} \]

puede encontrarse:

\[ P_o \]

muy alto.

Sin embargo, una parte de esa coincidencia puede explicarse por el predominio de la categoría.

Kappa intenta corregir parcialmente este fenómeno mediante:

\[ P_e \]


19. ¿Qué responde cada medida de concordancia?

Medida Pregunta
\(P_o\) ¿Qué proporción coincide realmente?
\(P_e\) ¿Qué acuerdo esperaríamos según las proporciones marginales?
\(\kappa\) ¿Cuánto supera el acuerdo observado al esperado?
IC de \(\kappa\) ¿Qué incertidumbre tiene la estimación?
Tabla ¿Dónde ocurren los desacuerdos?
Acuerdo por punto ¿En qué ubicaciones coinciden más los criterios?

20. Interpretación estadística integral de Kappa

Una redacción apropiada sería:

La clasificación global y la clasificación específica del punto coincidieron en el \(\ldots\%\) de los resultados. El acuerdo esperado fue de \(\ldots\%\). El índice Kappa de Cohen fue \(\kappa=\ldots\), con un intervalo de confianza aproximado de \(\ldots\) a \(\ldots\). Estos resultados indican un nivel de concordancia \(\ldots\) entre ambos criterios.


20.1 Interpretación microbiológica integral

La concordancia refleja hasta qué punto la identificación de resultados elevados es semejante cuando la referencia es toda la base o cuando se utiliza el comportamiento propio de cada punto. Los desacuerdos permiten detectar resultados que pueden ser moderados globalmente pero inusuales para una ubicación específica, así como resultados elevados globalmente que corresponden al comportamiento habitual de determinados puntos.

Un comportamiento habitualmente elevado no debe interpretarse como aceptable únicamente porque el resultado no supere el P90 específico del punto.


21. Ruta del análisis de concordancia

\[ \boxed{\text{Mismas observaciones}} \]

\[ \Downarrow \]

\[ \boxed{\text{Dos clasificaciones}} \]

\[ \Downarrow \]

\[ \boxed{\text{Tabla de concordancia}} \]

\[ \Downarrow \]

\[ \boxed{P_o} \]

\[ \Downarrow \]

\[ \boxed{P_e} \]

\[ \Downarrow \]

\[ \boxed{ \kappa= \frac{ P_o-P_e }{ 1-P_e } } \]

\[ \Downarrow \]

\[ \boxed{\text{IC de Kappa}} \]

\[ \Downarrow \]

\[ \boxed{\text{Revisión por punto}} \]

\[ \Downarrow \]

\[ \boxed{\text{Interpretación microbiológica}} \]


22. Comparación de los tres procedimientos

Procedimiento Estructura Medida principal Tamaño / magnitud Aplicación
Mann–Whitney Dos grupos independientes \(U/W\) \(r_{rb}\) Comparar dos puntos
Wilcoxon Dos mediciones pareadas \(W\) \(r_{rb}\) Comparar los mismos puntos entre periodos
Kappa Dos clasificaciones \(\kappa\) \(\kappa\) + IC Comparar criterios global y local

23. ¿Cómo seleccionar el procedimiento?

Si tenemos:

\[ \boxed{ \text{dos grupos diferentes e independientes} } \]

utilizamos:

\[ \boxed{\text{Mann–Whitney}} \]

Si tenemos:

\[ \boxed{ \text{las mismas unidades en dos condiciones} } \]

utilizamos:

\[ \boxed{\text{Wilcoxon signed-rank}} \]

Si tenemos:

\[ \boxed{ \text{dos clasificaciones de las mismas unidades} } \]

utilizamos:

\[ \boxed{\text{Kappa}} \]


24. Significación estadística y magnitud

Nunca debemos concluir solamente con:

\[ p<0.05 \]

Para Mann–Whitney debemos integrar:

\[ p+r_{rb}+\text{distribuciones} \]

Para Wilcoxon:

\[ p+r_{rb}+\text{diferencias} \]

Para Kappa:

\[ P_o+P_e+\kappa+IC \]


25. Significación estadística e importancia microbiológica

La inferencia estadística responde:

¿Existe evidencia de una diferencia o concordancia?

La interpretación microbiológica debe responder:

¿Qué representa esa diferencia o concordancia para el comportamiento de los puntos y la vigilancia microbiológica?

Ambas interpretaciones son necesarias.


26. Valores extremos

Los métodos de rangos presentan menor sensibilidad a valores extremos que los métodos basados directamente en medias.

Sin embargo, un resultado extremo no debe ignorarse.

Puede representar:

  • episodio microbiológico real;
  • condición ambiental;
  • cambio operacional;
  • problema analítico;
  • problema de muestreo.

Debe revisarse su trazabilidad.


27. Los métodos no paramétricos también necesitan gráficos

Mann–Whitney debe acompañarse de:

  • boxplot;
  • puntos individuales;
  • mediana;
  • IQR.

Wilcoxon debe acompañarse de:

  • diferencias;
  • gráfico pareado;
  • dirección del cambio.

Kappa debe acompañarse de:

  • tabla de concordancia;
  • frecuencias marginales;
  • patrón de desacuerdos.

28. Actividad de aplicación

Cada estudiante o grupo trabajará con el periodo asignado.

Para Mann–Whitney deberá:

  • seleccionar dos puntos;
  • justificar independencia;
  • realizar resumen descriptivo;
  • construir boxplot;
  • formular hipótesis;
  • explicar rangos;
  • calcular e interpretar U/W;
  • reportar valor \(p\);
  • intervalo cuando corresponda;
  • calcular tamaño del efecto;
  • realizar interpretación estadística;
  • realizar interpretación microbiológica.

Para Wilcoxon deberá:

  • seleccionar dos periodos;
  • identificar puntos comunes;
  • explicar el pareamiento;
  • calcular diferencias;
  • construir rangos con signo;
  • identificar \(W^+\) y \(W^-\);
  • ejecutar la prueba;
  • reportar \(p\);
  • estimar magnitud;
  • realizar interpretación estadística;
  • realizar interpretación microbiológica.

Para Kappa deberá:

  • construir dos clasificaciones;
  • realizar tabla de concordancia;
  • calcular \(P_o\);
  • calcular \(P_e\);
  • obtener \(\kappa\);
  • estimar intervalo de confianza;
  • estudiar desacuerdos;
  • analizar concordancia por punto;
  • realizar interpretación estadística;
  • realizar interpretación microbiológica.

29. Síntesis del módulo

1. Los métodos no paramétricos también poseen condiciones de aplicación.

2. Los rangos reducen la dependencia directa de la escala original.

3. Mann–Whitney compara dos grupos independientes.

4. Wilcoxon analiza diferencias dentro de pares.

5. El pareamiento debe respetar las mismas unidades de análisis.

6. El valor p no mide la magnitud de una diferencia.

7. Los tamaños del efecto complementan las pruebas no paramétricas.

8. Kappa cuantifica concordancia corregida por el acuerdo esperado.

9. Un porcentaje elevado de acuerdo no garantiza un Kappa elevado.

10. Concordancia no significa validez.

11. El punto de muestreo debe permanecer visible en la interpretación.

12. Toda conclusión debe integrar estadística y significado microbiológico.

Referencias

Blair, R. C., & Taylor, R. A. (2008). Bioestadística. Pearson Educación.

Bermúdez, J. D. (2013). Diez lecciones de estadística básica. Universitat de València.

Díaz Portillo, J. (2011). Guía práctica del curso de Bioestadística aplicada a las Ciencias de la Salud. Instituto Nacional de Gestión Sanitaria.

Yousefi, M., Najafi Saleh, H., Yaseri, M., Mahvi, A. H., Soleimani, H., Saeedi, Z., Zohdi, S., & Mohammadi, A. A. (2018). Data on microbiological quality assessment of rural drinking water supplies in Poldasht county. Data in Brief, 17, 763–769.