Análisis morfométrico comparativo: Tityus paraguayensis vs Tityus crypticus sp. nov.

De estadística descriptiva a multivariada y predictiva

Author

Cristian E. Granados-Martínez

0. Advertencia metodológica importante

Antes de cualquier análisis, hay que ser honestos con el tamaño de muestra:

  • Tityus paraguayensis: n = 7
  • Tityus crypticus sp. nov.: n = 4

Con muestras tan pequeñas (especialmente n = 4), pruebas como Shapiro-Wilk tienen muy poco poder estadístico, los intervalos de confianza son muy amplios, y técnicas como PCA con elipses o modelos predictivos con partición train/test no son confiables en sentido inferencial. Este script los incluye de todas formas porque son estándar en papers de morfometría taxonómica con series tipo pequeñas (común en Tityus), pero en cada sección se indica si el resultado es confirmatorio o solo exploratorio/descriptivo.

# Paquetes necesarios -------------------------------------------------------
paquetes <- c("tidyverse", "ggplot2", "corrplot", "psych", "rstatix",
              "vegan", "MASS", "factoextra", "FactoMineR", "knitr",
              "broom", "GGally")

instalar_faltantes <- paquetes[!paquetes %in% installed.packages()[, "Package"]]
if (length(instalar_faltantes) > 0) install.packages(instalar_faltantes)

invisible(lapply(paquetes, library, character.only = TRUE))

1. Carga y preparación de datos

datos <- read.csv("datos_escorpiones.csv", stringsAsFactors = FALSE)

datos$Especie <- factor(datos$Especie,
                         levels = c("Tityus_paraguayensis", "Tityus_crypticus_sp_nov"))

# Variables morfométricas (todas numéricas, excluyendo Especie)
vars_morfo <- names(datos)[-1]

str(datos)
'data.frame':   11 obs. of  9 variables:
 $ Especie          : Factor w/ 2 levels "Tityus_paraguayensis",..: 1 1 1 1 1 1 1 2 2 2 ...
 $ Total_length     : num  41.5 40.7 39.4 42.3 40.1 ...
 $ Prosoma_length   : num  5 5.37 5.61 5.98 5.49 5.61 5.61 4.63 4.88 4.51 ...
 $ Mesosoma_length  : num  10.67 10.24 8.17 10.61 9.15 ...
 $ Chela_length     : num  7.44 7.44 7.68 7.8 7.44 7.56 7.44 7.38 7.56 6.95 ...
 $ Chela_width      : num  2.07 1.95 2.32 2.38 2.07 2.07 2.07 2.2 2.32 2.07 ...
 $ Metasoma_V_length: num  5.49 5.37 5.73 5.85 5.85 5.85 5.73 4.63 4.39 4.39 ...
 $ Metasoma_V_width : num  2.44 2.44 2.62 2.68 2.44 2.44 2.56 2.32 2.32 2.2 ...
 $ Length_Telson    : num  4.02 3.9 4.51 4.39 3.9 4.39 4.39 3.54 3.54 3.29 ...
kable(datos)
Especie Total_length Prosoma_length Mesosoma_length Chela_length Chela_width Metasoma_V_length Metasoma_V_width Length_Telson
Tityus_paraguayensis 41.46 5.00 10.67 7.44 2.07 5.49 2.44 4.02
Tityus_paraguayensis 40.73 5.37 10.24 7.44 1.95 5.37 2.44 3.90
Tityus_paraguayensis 39.39 5.61 8.17 7.68 2.32 5.73 2.62 4.51
Tityus_paraguayensis 42.32 5.98 10.61 7.80 2.38 5.85 2.68 4.39
Tityus_paraguayensis 40.12 5.49 9.15 7.44 2.07 5.85 2.44 3.90
Tityus_paraguayensis 41.71 5.61 10.73 7.56 2.07 5.85 2.44 4.39
Tityus_paraguayensis 41.71 5.61 10.61 7.44 2.07 5.73 2.56 4.39
Tityus_crypticus_sp_nov 32.44 4.63 6.22 7.38 2.20 4.63 2.32 3.54
Tityus_crypticus_sp_nov 33.54 4.88 7.32 7.56 2.32 4.39 2.32 3.54
Tityus_crypticus_sp_nov 32.44 4.51 7.32 6.95 2.07 4.39 2.20 3.29
Tityus_crypticus_sp_nov 33.78 4.88 7.56 7.32 2.44 4.76 2.20 3.54

Verificación de tamaño de muestra por grupo (clave para interpretar todo lo que sigue):

datos %>%
  count(Especie, name = "n")
                  Especie n
1    Tityus_paraguayensis 7
2 Tityus_crypticus_sp_nov 4

2. Estadística descriptiva

# Resumen tipo "tabla morfométrica" de paper taxonómico
resumen_desc <- datos %>%
  pivot_longer(cols = all_of(vars_morfo), names_to = "Variable", values_to = "Valor") %>%
  group_by(Especie, Variable) %>%
  summarise(
    n      = n(),
    media  = mean(Valor),
    de     = sd(Valor),
    cv_pct = (de / media) * 100,
    minimo = min(Valor),
    maximo = max(Valor),
    .groups = "drop"
  ) %>%
  arrange(Variable, Especie)

kable(resumen_desc, digits = 2,
      caption = "Estadística descriptiva por especie y variable morfométrica")
Estadística descriptiva por especie y variable morfométrica
Especie Variable n media de cv_pct minimo maximo
Tityus_paraguayensis Chela_length 7 7.54 0.15 1.93 7.44 7.80
Tityus_crypticus_sp_nov Chela_length 4 7.30 0.26 3.51 6.95 7.56
Tityus_paraguayensis Chela_width 7 2.13 0.16 7.30 1.95 2.38
Tityus_crypticus_sp_nov Chela_width 4 2.26 0.16 7.04 2.07 2.44
Tityus_paraguayensis Length_Telson 7 4.21 0.26 6.24 3.90 4.51
Tityus_crypticus_sp_nov Length_Telson 4 3.48 0.12 3.59 3.29 3.54
Tityus_paraguayensis Mesosoma_length 7 10.03 0.99 9.85 8.17 10.73
Tityus_crypticus_sp_nov Mesosoma_length 4 7.11 0.60 8.46 6.22 7.56
Tityus_paraguayensis Metasoma_V_length 7 5.70 0.19 3.38 5.37 5.85
Tityus_crypticus_sp_nov Metasoma_V_length 4 4.54 0.18 4.05 4.39 4.76
Tityus_paraguayensis Metasoma_V_width 7 2.52 0.10 4.06 2.44 2.68
Tityus_crypticus_sp_nov Metasoma_V_width 4 2.26 0.07 3.07 2.20 2.32
Tityus_paraguayensis Prosoma_length 7 5.52 0.30 5.38 5.00 5.98
Tityus_crypticus_sp_nov Prosoma_length 4 4.72 0.19 3.93 4.51 4.88
Tityus_paraguayensis Total_length 7 41.06 1.03 2.51 39.39 42.32
Tityus_crypticus_sp_nov Total_length 4 33.05 0.71 2.15 32.44 33.78

Interpretación: el CV% (coeficiente de variación) ayuda a ver qué variables son más variables dentro de cada especie. Variables con CV bajo y consistentes entre individuos suelen ser más útiles como caracteres diagnósticos.

3. Razones morfométricas (índices diagnósticos)

En taxonomía de Tityus las razones (no solo las medidas brutas) suelen ser las que separan especies, porque controlan el efecto del tamaño corporal general.

datos_razones <- datos %>%
  mutate(
    Chela_L_W           = Chela_length / Chela_width,
    MetasomaV_L_W        = Metasoma_V_length / Metasoma_V_width,
    Mesosoma_Total       = Mesosoma_length / Total_length,
    Prosoma_Total         = Prosoma_length / Total_length,
    Telson_MetasomaV     = Length_Telson / Metasoma_V_length
  )

vars_razones <- c("Chela_L_W", "MetasomaV_L_W", "Mesosoma_Total",
                   "Prosoma_Total", "Telson_MetasomaV")

resumen_razones <- datos_razones %>%
  pivot_longer(cols = all_of(vars_razones), names_to = "Razon", values_to = "Valor") %>%
  group_by(Especie, Razon) %>%
  summarise(media = mean(Valor), de = sd(Valor), .groups = "drop")

kable(resumen_razones, digits = 3,
      caption = "Razones morfométricas por especie")
Razones morfométricas por especie
Especie Razon media de
Tityus_paraguayensis Chela_L_W 3.548 0.191
Tityus_paraguayensis Mesosoma_Total 0.244 0.019
Tityus_paraguayensis MetasomaV_L_W 2.265 0.094
Tityus_paraguayensis Prosoma_Total 0.135 0.007
Tityus_paraguayensis Telson_MetasomaV 0.740 0.038
Tityus_crypticus_sp_nov Chela_L_W 3.243 0.168
Tityus_crypticus_sp_nov Mesosoma_Total 0.215 0.016
Tityus_crypticus_sp_nov MetasomaV_L_W 2.012 0.112
Tityus_crypticus_sp_nov Prosoma_Total 0.143 0.003
Tityus_crypticus_sp_nov Telson_MetasomaV 0.766 0.028
datos_razones %>%
  pivot_longer(cols = all_of(vars_razones), names_to = "Razon", values_to = "Valor") %>%
  ggplot(aes(x = Especie, y = Valor, fill = Especie)) +
  geom_boxplot(alpha = 0.6) +
  geom_jitter(width = 0.1, size = 2) +
  facet_wrap(~Razon, scales = "free_y") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 30, hjust = 1)) +
  labs(title = "Razones morfométricas por especie", y = "Valor de la razón", x = NULL)
Figure 1: Comparación de razones morfométricas clave entre especies

4. Exploración gráfica de variables crudas

datos %>%
  pivot_longer(cols = all_of(vars_morfo), names_to = "Variable", values_to = "Valor") %>%
  ggplot(aes(x = Especie, y = Valor, fill = Especie)) +
  geom_boxplot(alpha = 0.6, outlier.shape = NA) +
  geom_jitter(width = 0.1, size = 2) +
  facet_wrap(~Variable, scales = "free_y") +
  theme_minimal() +
  theme(axis.text.x = element_blank(), legend.position = "bottom") +
  labs(title = "Variables morfométricas crudas por especie", x = NULL, y = "mm")
Figure 2: Distribución de cada variable morfométrica por especie
ggplot(datos, aes(x = Chela_length, y = Chela_width, color = Especie)) +
  geom_point(size = 3) +
  geom_smooth(method = "lm", se = FALSE, linetype = "dashed") +
  theme_minimal() +
  labs(title = "Largo vs ancho de quela", x = "Largo quela (mm)", y = "Ancho quela (mm)")
Figure 3: Relación largo vs ancho de quelas (carácter clásico en Tityus)

5. Supuestos: normalidad y homocedasticidad

⚠️ Con n = 4 y n = 7, Shapiro-Wilk tiene muy poco poder. Tómese como orientativo, no decisivo.

normalidad <- datos %>%
  pivot_longer(cols = all_of(vars_morfo), names_to = "Variable", values_to = "Valor") %>%
  group_by(Especie, Variable) %>%
  summarise(
    shapiro_p = tryCatch(shapiro.test(Valor)$p.value, error = function(e) NA),
    .groups = "drop"
  )

kable(normalidad, digits = 3,
      caption = "p-valores de Shapiro-Wilk por especie y variable (n bajo: interpretar con cautela)")
p-valores de Shapiro-Wilk por especie y variable (n bajo: interpretar con cautela)
Especie Variable shapiro_p
Tityus_paraguayensis Chela_length 0.022
Tityus_paraguayensis Chela_width 0.055
Tityus_paraguayensis Length_Telson 0.054
Tityus_paraguayensis Mesosoma_length 0.016
Tityus_paraguayensis Metasoma_V_length 0.055
Tityus_paraguayensis Metasoma_V_width 0.025
Tityus_paraguayensis Prosoma_length 0.518
Tityus_paraguayensis Total_length 0.625
Tityus_crypticus_sp_nov Chela_length 0.628
Tityus_crypticus_sp_nov Chela_width 0.976
Tityus_crypticus_sp_nov Length_Telson 0.001
Tityus_crypticus_sp_nov Mesosoma_length 0.076
Tityus_crypticus_sp_nov Metasoma_V_length 0.236
Tityus_crypticus_sp_nov Metasoma_V_width 0.024
Tityus_crypticus_sp_nov Prosoma_length 0.218
Tityus_crypticus_sp_nov Total_length 0.108
homogeneidad <- map_dfr(vars_morfo, function(v) {
  f <- as.formula(paste(v, "~ Especie"))
  lev <- rstatix::levene_test(datos, formula = f)
  lev$Variable <- v
  lev
})

kable(homogeneidad, digits = 3,
      caption = "Prueba de Levene (homogeneidad de varianzas) por variable")
Prueba de Levene (homogeneidad de varianzas) por variable
df1 df2 statistic p Variable
1 9 0.221 0.649 Total_length
1 9 0.091 0.770 Prosoma_length
1 9 0.333 0.578 Mesosoma_length
1 9 0.433 0.527 Chela_length
1 9 0.120 0.737 Chela_width
1 9 0.048 0.831 Metasoma_V_length
1 9 0.107 0.751 Metasoma_V_width
1 9 1.348 0.275 Length_Telson

6. Estadística confirmatoria univariada (comparación entre especies)

Dado el tamaño de muestra y la probable no-normalidad, se usa Mann-Whitney U (Wilcoxon) como prueba principal (más robusta), reportando t-test como referencia. Se aplica corrección de Holm por comparaciones múltiples (8 variables).

comparaciones <- map_dfr(vars_morfo, function(v) {
  f <- as.formula(paste(v, "~ Especie"))

  wilcox <- wilcox.test(f, data = datos)
  ttest  <- t.test(f, data = datos)

  tibble(
    Variable   = v,
    p_wilcoxon = wilcox.test(f, data = datos)$p.value,
    p_ttest    = t.test(f, data = datos)$p.value
  )
})

comparaciones <- comparaciones %>%
  mutate(
    p_wilcoxon_holm = p.adjust(p_wilcoxon, method = "holm"),
    p_ttest_holm    = p.adjust(p_ttest, method = "holm")
  )

kable(comparaciones, digits = 4,
      caption = "Comparación univariada entre especies (Wilcoxon y t-test, con corrección de Holm)")
Comparación univariada entre especies (Wilcoxon y t-test, con corrección de Holm)
Variable p_wilcoxon p_ttest p_wilcoxon_holm p_ttest_holm
Total_length 0.0104 0.0000 0.0696 0.0000
Prosoma_length 0.0099 0.0004 0.0696 0.0017
Mesosoma_length 0.0104 0.0002 0.0696 0.0010
Chela_length 0.0810 0.1574 0.1620 0.3148
Chela_width 0.2332 0.2522 0.2332 0.3148
Metasoma_V_length 0.0097 0.0000 0.0696 0.0002
Metasoma_V_width 0.0087 0.0009 0.0696 0.0028
Length_Telson 0.0092 0.0002 0.0696 0.0009

Lectura: con n tan bajo, exigir significancia tras corrección de Holm es un estándar muy estricto; aun si algunas variables no la superan, las diferencias en magnitud (ver sección de descriptivos y razones) siguen siendo informativas para la diagnosis taxonómica, apoyadas en evidencia morfológica cualitativa adicional que tú ya tienes en tu trabajo descriptivo.

7. Correlaciones

mat_cor <- cor(datos[, vars_morfo], method = "spearman")

corrplot(mat_cor, method = "color", type = "upper",
         addCoef.col = "black", number.cex = 0.7,
         tl.col = "black", tl.srt = 45,
         title = "Correlación de Spearman", mar = c(0,0,1,0))
Figure 4: Matriz de correlación de Spearman entre variables morfométricas (todas las muestras)
GGally::ggpairs(datos, columns = 2:5, aes(color = Especie, alpha = 0.6)) +
  theme_minimal()
Figure 5: Matriz de dispersión por pares, coloreada por especie

8. Estadística multivariada

8.1 PCA (Análisis de Componentes Principales)

⚠️ Exploratorio: con n = 11 total, el PCA sirve para visualizar patrones de agrupamiento, no para inferencia confirmatoria. No se incluyen elipses de confianza por ser poco fiables con n = 4 en un grupo.

pca_res <- prcomp(datos[, vars_morfo], scale. = TRUE)

summary(pca_res)
Importance of components:
                          PC1    PC2     PC3     PC4     PC5     PC6     PC7
Standard deviation     2.4096 1.2299 0.49983 0.43576 0.32189 0.28778 0.22873
Proportion of Variance 0.7258 0.1891 0.03123 0.02374 0.01295 0.01035 0.00654
Cumulative Proportion  0.7258 0.9149 0.94611 0.96984 0.98279 0.99315 0.99969
                           PC8
Standard deviation     0.05013
Proportion of Variance 0.00031
Cumulative Proportion  1.00000
fviz_pca_biplot(pca_res,
                 habillage = datos$Especie,
                 addEllipses = FALSE,
                 label = "var",
                 repel = TRUE) +
  theme_minimal() +
  labs(title = "PCA - Biplot morfométrico")
Figure 6: Biplot de PCA: individuos y variables
fviz_eig(pca_res, addlabels = TRUE) +
  labs(title = "Varianza explicada por componente principal")
Figure 7: Varianza explicada por componente

8.2 PERMANOVA (alternativa robusta a MANOVA con n bajo)

dist_euclid <- vegdist(scale(datos[, vars_morfo]), method = "euclidean")

set.seed(123)
permanova_res <- adonis2(dist_euclid ~ Especie, data = datos, permutations = 999)
permanova_res
Permutation test for adonis under reduced model
Permutation: free
Number of permutations: 999

adonis2(formula = dist_euclid ~ Especie, data = datos, permutations = 999)
         Df SumOfSqs     R2      F Pr(>F)   
Model     1   52.432 0.6554 17.118  0.006 **
Residual  9   27.568 0.3446                 
Total    10   80.000 1.0000                 
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Nota: con n = 4 en un grupo, el número de permutaciones únicas posibles es limitado, por lo que el p-valor de PERMANOVA debe interpretarse como orientativo, no como prueba dura.

8.3 Análisis Discriminante Lineal (LDA) — clasificador exploratorio

lda_res <- lda(Especie ~ ., data = datos[, c("Especie", vars_morfo)])
lda_res
Call:
lda(Especie ~ ., data = datos[, c("Especie", vars_morfo)])

Prior probabilities of groups:
   Tityus_paraguayensis Tityus_crypticus_sp_nov 
              0.6363636               0.3636364 

Group means:
                        Total_length Prosoma_length Mesosoma_length
Tityus_paraguayensis        41.06286       5.524286        10.02571
Tityus_crypticus_sp_nov     33.05000       4.725000         7.10500
                        Chela_length Chela_width Metasoma_V_length
Tityus_paraguayensis        7.542857    2.132857          5.695714
Tityus_crypticus_sp_nov     7.302500    2.257500          4.542500
                        Metasoma_V_width Length_Telson
Tityus_paraguayensis            2.517143      4.214286
Tityus_crypticus_sp_nov         2.260000      3.477500

Coefficients of linear discriminants:
                         LD1
Total_length      -11.981374
Prosoma_length     -4.325275
Mesosoma_length    12.809145
Chela_length       17.312835
Chela_width         5.603882
Metasoma_V_length  13.095573
Metasoma_V_width   17.799225
Length_Telson      -3.136275
pred_lda <- predict(lda_res)
tabla_clasif <- table(Real = datos$Especie, Predicho = pred_lda$class)
kable(tabla_clasif, caption = "Matriz de confusión (ajuste interno, NO validación externa)")
Matriz de confusión (ajuste interno, NO validación externa)
Tityus_paraguayensis Tityus_crypticus_sp_nov
Tityus_paraguayensis 7 0
Tityus_crypticus_sp_nov 0 4

⚠️ Importante: esta matriz de confusión es sobre los mismos datos de entrenamiento (no hay datos suficientes para separar train/test). Una clasificación “perfecta” aquí es esperable por sobreajuste y no implica que el modelo generalice a nuevos individuos. Se reporta solo como ejercicio exploratorio de separación morfométrica, no como modelo predictivo validado.

9. Sobre “modelos predictivos”

Con n = 11 (7 vs 4), construir un modelo predictivo válido (regresión logística con partición train/test, random forest, etc.) no es metodológicamente defendible: el modelo memorizaría los datos en vez de aprender un patrón generalizable, y cualquier métrica de “accuracy” sería ilusoria.

Lo que sí es razonable y se hizo arriba: - LDA como herramienta exploratoria de separación morfológica (sección 8.3). - PERMANOVA como prueba multivariada de diferencia entre grupos (sección 8.2).

Si en el futuro amplías la serie (más individuos, quizá de otras localidades o de series tipo adicionales), ahí sí valdría la pena revisar un modelo predictivo con validación cruzada (leave-one-out, dado que con esos tamaños tampoco alcanzaría para train/test clásico).

10. Resumen ejecutivo

cat("Resumen de hallazgos:\n",
    "- n por especie: paraguayensis = 7, crypticus sp. nov. = 4 (muestra pequeña).\n",
    "- Variables con menor solapamiento aparente (ver boxplots y descriptivos):",
    "revisar Total_length, Mesosoma_length y razones Mesosoma_Total.\n",
    "- PERMANOVA y PCA sugieren separación multivariada entre especies (exploratorio).\n",
    "- LDA logra separación perfecta en ajuste interno (esperable, no validación real).\n",
    "- Recomendación: complementar con más individuos y caracteres cualitativos",
    "para fortalecer la diagnosis.\n")
Resumen de hallazgos:
 - n por especie: paraguayensis = 7, crypticus sp. nov. = 4 (muestra pequeña).
 - Variables con menor solapamiento aparente (ver boxplots y descriptivos): revisar Total_length, Mesosoma_length y razones Mesosoma_Total.
 - PERMANOVA y PCA sugieren separación multivariada entre especies (exploratorio).
 - LDA logra separación perfecta en ajuste interno (esperable, no validación real).
 - Recomendación: complementar con más individuos y caracteres cualitativos para fortalecer la diagnosis.