# Paquetes utilizados. Si falta alguno: install.packages(c("dplyr","tidyr","ggplot2"))
library(dplyr)    # manipulación de datos
library(tidyr)    # reorganización de tablas (formato largo/ancho)
library(ggplot2)  # figuras publicables (Grammar of Graphics)
library(knitr)    # tablas con kable() y renderizado del documento
# Carpeta donde están los archivos .txt (cápsula de captura-recaptura + clima).
# Por defecto, la misma carpeta del .Rmd. Cambiar si los datos están en otro lugar.
data_dir <- "."

Título y autores

Artículo replicado: Cayuela, H., Griffiths, R. A., Zakaria, N., Arntzen, J. W., Priol, P., Léna, J.-P., Besnard, A., & Joly, P. (2020). Drivers of amphibian population dynamics and asynchrony at local and regional scales. Journal of Animal Ecology, 89(6), 1350–1364. https://doi.org/10.1111/1365-2656.13208. Datos: Dryad https://doi.org/10.5061/dryad.573n5tb46.

Nota metodológica importante (leer antes de evaluar). La guía del taller describe el Artículo #10 como “regresión logística binaria (presencia/ausencia) y modelos de ocupación”. Sin embargo, el artículo original no es un estudio de ocupación: utiliza modelos multi-evento de captura–recaptura (programa E-SURGE) para estimar supervivencia y reclutamiento, modelos espacio-estado de Gompertz para densidad-dependencia y partición de varianza para medir sincronía. Los datos abiertos son historiales de captura–recaptura (individuos × ocasiones), no una tabla presencia ~ área_humedal + cobertura. Para respetar el método solicitado por el curso (GLM binomial) usando los datos reales, modelamos una variable binaria genuina: la detección/recaptura de cada tritón (detectado = 1 / no detectado = 0) en los años en que con certeza estaba presente, en función del sexo y de las covariables climáticas. Esta es la cantidad que, en captura–recaptura, se denomina probabilidad de recaptura (\(p\)) y es uno de los parámetros centrales del artículo. El desajuste entre el método pedido y el método original se discute críticamente en la Sección @ref(discusion).

Abstract

La sincronía poblacional regional puede surgir por forzamiento climático común (efecto Moran), mientras que factores locales como la densidad-dependencia y la heterogeneidad de detección la reducen. Cayuela et al. (2020) analizaron cinco poblaciones europeas del tritón crestado Triturus cristatus con captura–recaptura y concluyeron que el clima tiene efectos débiles y espacialmente variables, y que la densidad-dependencia es generalizada, produciendo baja sincronía. En esta réplica trabajamos con los datos abiertos de Dryad (historiales de captura–recaptura de 4 715 individuos y series climáticas z-estandarizadas). Como el curso solicita una regresión logística binaria, modelamos la probabilidad de detección/recaptura —una respuesta binaria real de estos datos— en función del sexo y de cuatro covariables climáticas, ajustando un glm binomial por población. La detección observada fue alta (0.70–0.97) y mostró efecto significativo del sexo en POP1, POP2 y POP4 (machos más detectables), consistente con su mayor actividad reproductiva. Los efectos climáticos resultaron débiles, inconsistentes en signo y dependientes de la población, reproduciendo cualitativamente el hallazgo principal del artículo original. Concluimos que, aun con un método más simple que el multi-evento, emerge el mismo patrón biológico: la dinámica de detección y demografía del tritón depende más de factores locales que de un forzamiento climático regional común.

1 Introducción

Entender qué regula las fluctuaciones poblacionales es central en ecología y conservación. Cuando poblaciones distantes oscilan de forma sincronizada suele invocarse el efecto Moran: perturbaciones ambientales correlacionadas (temperatura, precipitación) imponen un ritmo común. No obstante, la sincronía observada suele ocurrir a escalas espaciales mucho menores que las del clima, lo que sugiere que factores locales —densidad-dependencia, características del hábitat, heterogeneidad en la detección de individuos— amortiguan ese forzamiento común.

Los anfibios de reproducción en charcas son un modelo ideal: son sensibles al clima pero su demografía es muy dependiente del contexto local (calidad de la charca, densidad larvaria, competencia). Cayuela et al. (2020) estudiaron el tritón crestado, especie en declive y protegida por la Directiva Hábitats europea, en cinco poblaciones (Inglaterra y Francia) durante hasta 22 años.

Pregunta de investigación original: ¿el clima regional genera sincronía demográfica (supervivencia, reclutamiento, crecimiento poblacional) entre poblaciones, o predominan factores locales que la reducen?

Pregunta de esta réplica (adaptada al método del curso): ¿la probabilidad de detectar/recapturar un tritón depende del sexo y de las condiciones climáticas anuales, y ese efecto es consistente entre poblaciones o heterogéneo (como predice el artículo para los parámetros demográficos)? Si el clima influyera de forma fuerte y homogénea, esperaríamos coeficientes climáticos grandes y del mismo signo en todas las poblaciones; si dominan los factores locales, esperaríamos efectos débiles e inconsistentes.

2 Materiales y Métodos

2.1 Origen de los datos

Datos públicos del repositorio Dryad (https://doi.org/10.5061/dryad.573n5tb46), correspondientes al artículo original. Por cada población hay dos archivos de texto:

  • POPx_capture-recapture_data.txt: una fila por individuo. Las columnas H: son las ocasiones de muestreo anuales (1 = capturado, 0 = no capturado); S: es la frecuencia del historial (siempre 1) y $COV:SEX el sexo. POP5 incluye además $COV:SITE (subpoblación).
  • POPx_weather_data.txt: primera línea = número de covariables (6); segunda = número de años por covariable; luego una fila por covariable con valores z-estandarizados.

Según el artículo, las covariables climáticas corresponden a la precipitación acumulada en el periodo reproductivo y no-reproductivo y a temperaturas mínima y máxima invernales (o del periodo no-activo, en POP4). Como los archivos públicos no traen etiquetas, las denotamos de forma conservadora clima1clima6 y usamos las cuatro primeras como predictores focales.

2.2 Software

R version 4.5.1 (2025-06-13 ucrt), con los paquetes dplyr, tidyr, ggplot2 y knitr (ver Sección de Referencias para las citas formales). El artículo original usó E-SURGE (multi-evento) y JAGS (modelos bayesianos espacio-estado), software especializado que aquí no replicamos por diseño.

2.3 Lectura y preparación de los datos (código comentado)

# --- Normaliza la codificación del sexo a "F"/"M" entre poblaciones ---
# POP1/2/4 usan "Female/Male"; POP3 usa "F/M"; POP5 usa "1/2".
# Asumimos la convención E-SURGE 1 = hembra, 2 = macho (efecto de sexo es
# marginal según el artículo, por lo que un eventual intercambio no altera
# las conclusiones).
normaliza_sexo <- function(s) {
  dplyr::recode(as.character(s),
                "Female"="F","Male"="M","F"="F","M"="M",
                "1"="F","2"="M", .default = NA_character_)
}

# --- Lee un archivo de captura-recaptura en formato E-SURGE ---
leer_captura <- function(pop, dir = data_dir) {
  raw <- gsub("\r$", "",
              readLines(file.path(dir, paste0(pop, "_capture-recapture_data.txt")),
                        warn = FALSE))
  header <- strsplit(raw[1], "\t")[[1]]
  n_occ  <- sum(header == "H:")              # número de ocasiones (años)
  has_site <- any(grepl("SITE", header))      # ¿hay subpoblación? (POP5)
  cuerpo <- raw[-1]; cuerpo <- cuerpo[nchar(trimws(cuerpo)) > 0]
  sp <- strsplit(cuerpo, "\t")
  H   <- t(sapply(sp, function(x) as.integer(x[1:n_occ])))   # matriz indiv x años
  sex <- normaliza_sexo(sapply(sp, function(x) x[n_occ + 2]))
  site <- if (has_site) sapply(sp, function(x) x[n_occ + 3]) else rep(NA, length(sp))
  list(H = H, sex = sex, site = site, n_occ = n_occ)
}

# --- Lee el archivo climático y devuelve una matriz (covariables x años) ---
leer_clima <- function(pop, dir = data_dir) {
  raw <- gsub("\r$", "",
              readLines(file.path(dir, paste0(pop, "_weather_data.txt")), warn = FALSE))
  n_cov <- as.integer(strsplit(trimws(raw[1]), "\\s+")[[1]][1])
  M <- do.call(rbind, lapply(raw[3:(2 + n_cov)],
               function(l) as.numeric(strsplit(trimws(l), "\\s+")[[1]])))
  rownames(M) <- paste0("clima", seq_len(nrow(M)))
  M
}

poblaciones <- paste0("POP", 1:5)

2.4 Construcción de la variable respuesta (detección “presencia/ausencia”)

Para que la regresión logística sea biológicamente limpia, usamos el truco estándar de los “años en que el individuo está vivo con certeza”: entre su primera y última captura, el animal estaba necesariamente presente en la población. En las ocasiones interiores de ese intervalo, el valor 1/0 indica si fue detectado dado que estaba presente — exactamente la probabilidad de recaptura \(p\). Esto evita confundir detección con supervivencia o reclutamiento.

# Devuelve un data.frame (individuo x ocasión interior) con la respuesta binaria
# 'detectado' y las covariables de ese año (sexo, subpoblación y clima1..4).
build_deteccion <- function(pop) {
  cr <- leer_captura(pop); cl <- leer_clima(pop)
  H <- cr$H; T <- cr$n_occ; filas <- list()
  for (i in seq_len(nrow(H))) {
    caps <- which(H[i, ] == 1)
    if (length(caps) >= 2) {                       # necesita >=2 capturas
      interiores <- (min(caps) + 1):(max(caps) - 1) # ocasiones "vivo seguro"
      interiores <- interiores[interiores >= 2 & interiores <= T]
      for (t in interiores) {
        # El clima del año t se alinea con la columna (t-1) (intervalo previo)
        filas[[length(filas) + 1]] <- data.frame(
          pop = pop, id = i, occ = t,
          sexo = cr$sex[i], site = cr$site[i],
          detectado = H[i, t],
          clima1 = cl[1, t-1], clima2 = cl[2, t-1],
          clima3 = cl[3, t-1], clima4 = cl[4, t-1])
      }
    }
  }
  if (length(filas) == 0) return(NULL)
  dplyr::bind_rows(filas)
}

# Dataset combinado de las 5 poblaciones
det <- dplyr::bind_rows(lapply(poblaciones, build_deteccion))
det$sexo <- factor(det$sexo)
det$pop  <- factor(det$pop, levels = poblaciones)

2.5 Análisis estadístico, justificación y supuestos

Ajustamos, por población, un modelo lineal generalizado binomial (función de enlace logit):

\[\text{logit}\big(P(\text{detectado}_{it}=1)\big)=\beta_0+\beta_{\text{sexo}}\,\text{sexo}_i+\sum_{k=1}^{4}\beta_k\,\text{clima}_{k,t}\]

Por qué este método es adecuado. La respuesta es binaria (detectado/no detectado), por lo que la regresión logística es la herramienta canónica: modela la probabilidad en escala logit garantizando predicciones en \([0,1]\) y entrega coeficientes interpretables como odds ratios. Es el mismo enlace que usan los modelos de ocupación y de captura–recaptura para el componente de detección.

Supuestos y limitaciones. (i) Independencia condicional de las observaciones: incluimos varias ocasiones por individuo, lo que introduce pseudoreplicación leve; un modelo mixto con efecto aleatorio por individuo sería más estricto (lo señalamos como mejora). (ii) El clima es constante dentro de un año (covariable a nivel de ocasión). (iii) Asumimos que entre primera y última captura no hubo emigración temporal permanente. (iv) En POP3 hay pocos años (7), por lo que algunos coeficientes climáticos son inestables (errores estándar grandes); lo reportamos con transparencia.

3 Resultados

3.1 Descripción de los datos

# Tabla 1: resumen por población
resumen <- det %>%
  group_by(pop) %>%
  summarise(
    `Individuos (con >=2 capturas)` = n_distinct(id),
    `Observaciones indiv-año`       = n(),
    `% machos`                      = round(100*mean(sexo=="M", na.rm=TRUE), 1),
    `Tasa de detección observada`   = round(mean(detectado), 3),
    .groups = "drop")
kable(resumen, caption = "Tabla 1. Resumen del conjunto de datos de detección por población.")
Tabla 1. Resumen del conjunto de datos de detección por población.
pop Individuos (con >=2 capturas) Observaciones indiv-año % machos Tasa de detección observada
POP1 482 1022 57.1 0.695
POP2 97 336 56.5 0.872
POP3 102 251 26.3 0.948
POP4 334 603 49.3 0.751
POP5 549 991 50.2 0.973
# Conteo de capturas por ocasión (año) y población
capturas_anio <- bind_rows(lapply(poblaciones, function(p){
  cr <- leer_captura(p)
  data.frame(pop = p, occ = seq_len(cr$n_occ),
             capturados = colSums(cr$H))
}))
capturas_anio$pop <- factor(capturas_anio$pop, levels = poblaciones)

ggplot(capturas_anio, aes(occ, capturados)) +
  geom_line(color = "#2E7D32") + geom_point(color = "#2E7D32", size = 1.4) +
  facet_wrap(~pop, scales = "free", ncol = 3) +
  labs(x = "Ocasión de muestreo (año relativo)",
       y = "N.º de individuos capturados") +
  theme_minimal(base_size = 12)
Figura 1. Número de tritones capturados por año en cada población (proxy del tamaño poblacional, análogo a la Figura 1 del artículo original). Las poblaciones fluctúan de forma marcada y poco sincronizada.

Figura 1. Número de tritones capturados por año en cada población (proxy del tamaño poblacional, análogo a la Figura 1 del artículo original). Las poblaciones fluctúan de forma marcada y poco sincronizada.

det_anio <- det %>% group_by(pop, occ) %>%
  summarise(p_det = mean(detectado), n = n(), .groups="drop")

ggplot(det_anio, aes(occ, p_det)) +
  geom_line(color="#1565C0") + geom_point(aes(size=n), color="#1565C0", alpha=.6) +
  facet_wrap(~pop, scales="free_x", ncol=3) +
  scale_size_continuous(name="n obs", range=c(.5,3)) +
  labs(x="Ocasión de muestreo (año relativo)", y="Probabilidad de detección observada") +
  ylim(0,1) + theme_minimal(base_size = 12)
Figura 2. Tasa de detección observada por año (solo individuos vivos con certeza). La detección es alta pero variable entre años y poblaciones.

Figura 2. Tasa de detección observada por año (solo individuos vivos con certeza). La detección es alta pero variable entre años y poblaciones.

3.2 Modelos logísticos por población

# Ajusta un GLM binomial por población. Si una población tiene un solo sexo,
# se omite el término 'sexo' automáticamente.
ajustar_glm <- function(p) {
  d <- droplevels(filter(det, pop == p))
  fml <- if (nlevels(d$sexo) > 1)
            detectado ~ sexo + clima1 + clima2 + clima3 + clima4
         else detectado ~ clima1 + clima2 + clima3 + clima4
  glm(fml, data = d, family = binomial)
}
modelos <- setNames(lapply(poblaciones, ajustar_glm), poblaciones)

# Extrae coeficientes en escala de odds ratio con IC95% (Wald) y p-valor
tabla_coef <- function(p) {
  m <- modelos[[p]]; co <- summary(m)$coefficients
  ic <- suppressMessages(confint.default(m))
  data.frame(pop = p, termino = rownames(co),
             OR = exp(co[,1]),
             IC_inf = exp(ic[,1]), IC_sup = exp(ic[,2]),
             p_valor = co[,4], row.names = NULL)
}
coefs <- bind_rows(lapply(poblaciones, tabla_coef))
# Tabla 2: coeficientes (odds ratios) de todos los modelos
coefs_print <- coefs %>%
  mutate(across(c(OR, IC_inf, IC_sup), ~round(.,3)),
         p_valor = signif(p_valor, 3),
         signif. = ifelse(p_valor < 0.05, "*", ""))
kable(coefs_print,
      caption = "Tabla 2. Odds ratios (OR), intervalos de confianza al 95% y p-valores de los modelos logísticos de detección por población. OR>1: mayor probabilidad de detección. * = p<0.05.")
Tabla 2. Odds ratios (OR), intervalos de confianza al 95% y p-valores de los modelos logísticos de detección por población. OR>1: mayor probabilidad de detección. * = p<0.05.
pop termino OR IC_inf IC_sup p_valor signif.
POP1 (Intercept) 1.707 1.393 2.092 3.00e-07 *
POP1 sexoM 1.509 1.140 1.997 4.02e-03 *
POP1 clima1 1.169 0.827 1.652 3.77e-01
POP1 clima2 0.576 0.401 0.827 2.81e-03 *
POP1 clima3 0.855 0.695 1.051 1.36e-01
POP1 clima4 0.846 0.672 1.066 1.56e-01
POP2 (Intercept) 5.681 3.338 9.668 0.00e+00 *
POP2 sexoM 2.818 1.402 5.664 3.63e-03 *
POP2 clima1 0.650 0.258 1.637 3.61e-01
POP2 clima2 2.083 0.778 5.581 1.44e-01
POP2 clima3 1.838 1.082 3.121 2.43e-02 *
POP2 clima4 1.250 0.781 2.003 3.53e-01
POP3 (Intercept) 24.465 9.827 60.912 0.00e+00 *
POP3 sexoM 1.326 0.347 5.067 6.80e-01
POP3 clima1 13.044 0.038 4444.736 3.88e-01
POP3 clima2 0.228 0.000 280.347 6.84e-01
POP3 clima3 1.426 0.307 6.611 6.50e-01
POP3 clima4 0.474 0.029 7.686 5.99e-01
POP4 (Intercept) 3.104 2.291 4.206 0.00e+00 *
POP4 sexoM 2.048 1.378 3.043 3.90e-04 *
POP4 clima1 0.771 0.627 0.947 1.34e-02 *
POP4 clima2 1.835 1.214 2.774 4.01e-03 *
POP4 clima3 0.685 0.454 1.033 7.11e-02
POP4 clima4 3.502 1.908 6.428 5.25e-05 *
POP5 (Intercept) 56.381 28.874 110.093 0.00e+00 *
POP5 sexoM 0.551 0.248 1.223 1.43e-01
POP5 clima1 0.974 0.514 1.844 9.35e-01
POP5 clima2 1.513 0.661 3.461 3.27e-01
POP5 clima3 0.776 0.511 1.176 2.31e-01
POP5 clima4 0.640 0.419 0.978 3.89e-02 *
# Pseudo-R2 de McFadden y % de clasificación correcta (umbral 0.5)
metricas <- bind_rows(lapply(poblaciones, function(p){
  m <- modelos[[p]]
  # Pseudo-R2 (McFadden) basado en deviances que el propio glm almacena:
  mcf <- 1 - m$deviance / m$null.deviance
  acc <- mean((fitted(m) > 0.5) == (m$y == 1))
  data.frame(pop = p, `Pseudo-R2 McFadden` = round(mcf,3),
             `% clasificación correcta` = round(100*acc,1),
             check.names = FALSE)
}))
kable(metricas, caption = "Tabla 3. Métricas de ajuste de los modelos logísticos.")
Tabla 3. Métricas de ajuste de los modelos logísticos.
pop Pseudo-R2 McFadden % clasificación correcta
POP1 0.053 72.1
POP2 0.117 87.2
POP3 0.056 94.8
POP4 0.069 77.4
POP5 0.035 97.3
coef_plot <- coefs %>% filter(termino != "(Intercept)")
ggplot(coef_plot, aes(x = OR, y = termino, color = pop)) +
  geom_vline(xintercept = 1, linetype = 2, color = "grey50") +
  geom_point(position = position_dodge(width = .6)) +
  geom_errorbarh(aes(xmin = IC_inf, xmax = IC_sup),
                 height = .25, position = position_dodge(width = .6)) +
  scale_x_log10() +
  labs(x = "Odds ratio (escala log)", y = NULL, color = "Población") +
  theme_minimal(base_size = 12)
Figura 3. Efecto de las covariables (odds ratios e IC95%) sobre la probabilidad de detección, por población. La línea vertical en OR=1 indica ausencia de efecto. Los efectos climáticos son débiles e inconsistentes en signo entre poblaciones; el sexo (machos) es el predictor más recurrente.

Figura 3. Efecto de las covariables (odds ratios e IC95%) sobre la probabilidad de detección, por población. La línea vertical en OR=1 indica ausencia de efecto. Los efectos climáticos son débiles e inconsistentes en signo entre poblaciones; el sexo (machos) es el predictor más recurrente.

# Curva de predicción para una población con efecto climático claro (POP4)
d4 <- droplevels(filter(det, pop == "POP4"))
m4 <- modelos[["POP4"]]
rejilla <- expand.grid(
  sexo = levels(d4$sexo),
  clima4 = seq(min(d4$clima4), max(d4$clima4), length.out = 100),
  clima1 = 0, clima2 = 0, clima3 = 0)          # demás covariables en su media (z=0)
rejilla$pred <- predict(m4, newdata = rejilla, type = "response")

ggplot() +
  geom_jitter(data = d4, aes(clima4, detectado, color = sexo),
              height = .03, width = 0, alpha = .15) +
  geom_line(data = rejilla, aes(clima4, pred, color = sexo), linewidth = 1.2) +
  labs(x = "Covariable climática clima4 (z-estandarizada)",
       y = "Probabilidad de detección", color = "Sexo") +
  theme_minimal(base_size = 12)
Figura 4. Probabilidad de detección predicha en POP4 frente a la covariable climática clima4 (la de efecto más fuerte), por sexo. Estilo de figura solicitado en la guía del taller: puntos = observaciones, líneas = predicción del modelo.

Figura 4. Probabilidad de detección predicha en POP4 frente a la covariable climática clima4 (la de efecto más fuerte), por sexo. Estilo de figura solicitado en la guía del taller: puntos = observaciones, líneas = predicción del modelo.

3.3 Análisis secundario: subpoblaciones de POP5 (sabor “ocupación local”)

d5 <- droplevels(filter(det, pop == "POP5"))
d5$site <- factor(d5$site)
# Modelo con subpoblación como factor (efecto espacial local)
m5_site <- glm(detectado ~ site + clima1 + clima2, data = d5, family = binomial)

d5 %>% group_by(site) %>%
  summarise(p_det = mean(detectado), n = n(), .groups="drop") %>%
  ggplot(aes(site, p_det)) +
  geom_col(fill = "#6A1B9A", alpha=.8) +
  geom_text(aes(label = n), vjust = -0.4, size = 3) +
  ylim(0,1) +
  labs(x = "Subpoblación (SITE) en POP5", y = "Detección observada",
       caption = "Etiqueta = n.º de observaciones") +
  theme_minimal(base_size = 12)
Figura 5. Tasa de detección por subpoblación (SITE) en POP5. Permite explorar heterogeneidad espacial local, en línea con el análisis de sincronía dentro de POP5 del artículo.

Figura 5. Tasa de detección por subpoblación (SITE) en POP5. Permite explorar heterogeneidad espacial local, en línea con el análisis de sincronía dentro de POP5 del artículo.

4 Discusión

4.1 Interpretación biológica

La probabilidad de detección fue alta (0.70–0.97), coherente con un muestreo intensivo de tritones que regresan a las charcas para reproducirse. El predictor más consistente fue el sexo: en POP1, POP2 y POP4 los machos tuvieron mayor probabilidad de ser detectados (OR > 1, p < 0.05). Esto es biológicamente esperable, porque los machos despliegan conductas reproductivas más conspicuas y permanecen más tiempo activos en la charca, aumentando su captura. El artículo original también reporta que el sexo tiene un efecto, en general, marginal sobre los parámetros demográficos (supervivencia y reclutamiento), de modo que su señal aquí aparece sobre todo en la detección, no en la demografía.

Los efectos del clima fueron débiles, inconsistentes en signo y dependientes de la población: clima2 reduce la detección en POP1 pero clima3 la aumenta en POP2, y POP4 muestra el efecto positivo más marcado (clima4), mientras POP3 y POP5 apenas responden. Esta heterogeneidad espacial es precisamente el resultado central de Cayuela et al. (2020): el clima tiene efectos “weak and spatially variable” sobre supervivencia, reclutamiento y crecimiento. Nuestra réplica, con un método más simple, recupera el mismo patrón cualitativo: si existiera un forzamiento climático regional fuerte y común (efecto Moran), los coeficientes climáticos serían grandes y del mismo signo en todas las poblaciones, y no lo son.

4.2 Limitaciones

  1. Detección ≠ ocupación ≠ demografía. Modelamos la probabilidad de recaptura, no la supervivencia/reclutamiento que estima el artículo. Es un subcomponente del proceso, elegido para encajar con el GLM binomial pedido.
  2. Pseudoreplicación: varias observaciones por individuo violan la independencia estricta; un GLMM con efecto aleatorio por individuo (lme4::glmer) sería la mejora natural.
  3. Covariables sin etiqueta: los archivos públicos no nombran clima1–6; usamos las cuatro primeras de forma conservadora.
  4. POP3 tiene pocos años, lo que infla los errores estándar de sus coeficientes climáticos.

4.3 Comparación crítica con el artículo original

Aspecto Artículo (Cayuela et al. 2020) Esta réplica
Método Multi-evento (E-SURGE), Gompertz espacio-estado, partición de varianza GLM logístico binomial por población
Parámetro modelado Supervivencia, reclutamiento, crecimiento, sincronía Probabilidad de detección/recaptura
Manejo de heterogeneidad Mezclas de Pledger en la recaptura Sexo + subpoblación como covariables
Efecto del clima Débil y espacialmente variable Débil e inconsistente (igual conclusión)
Efecto del sexo Marginal en demografía Significativo en detección (POP1/2/4)

Semejanzas: ambos análisis concluyen que el clima no actúa como sincronizador fuerte y que existe heterogeneidad entre poblaciones, lo que respalda un efecto Moran débil. Diferencias: el artículo separa explícitamente detección de supervivencia mediante modelos multi-evento y mide densidad-dependencia y sincronía (ICC), aspectos que nuestro GLM no aborda. Por tanto, nuestra réplica es parcial pero consistente: confirma el mensaje ecológico central con una herramienta más accesible, evidenciando a la vez por qué el equipo original necesitó modelos más complejos para estimar la demografía sin sesgo por detección imperfecta.

Código reproducible

Todo el código está incluido arriba con echo = TRUE y comentado. El documento se renderiza con rmarkdown::render("este_archivo.Rmd"). Los archivos .txt deben estar en la carpeta indicada por data_dir (por defecto, la del .Rmd).

Referencias

Artículo original

Cayuela, H., Griffiths, R. A., Zakaria, N., Arntzen, J. W., Priol, P., Léna, J.-P., Besnard, A., & Joly, P. (2020). Drivers of amphibian population dynamics and asynchrony at local and regional scales. Journal of Animal Ecology, 89(6), 1350–1364. https://doi.org/10.1111/1365-2656.13208

Paquetes de R (generados con citation()):

for (pkg in c("base","dplyr","tidyr","ggplot2","knitr","rmarkdown")) {
  cat("\n\n*", pkg, "*\n\n")
  print(citation(pkg), style = "text")
}
  • base *

R Core Team (2025). R: A Language and Environment for Statistical Computing. R Foundation for Statistical Computing, Vienna, Austria. https://www.R-project.org/.

  • dplyr *

Wickham H, François R, Henry L, Müller K, Vaughan D (2026). dplyr: A Grammar of Data Manipulation. doi:10.32614/CRAN.package.dplyr https://doi.org/10.32614/CRAN.package.dplyr, R package version 1.2.0, https://CRAN.R-project.org/package=dplyr.

  • tidyr *

Wickham H, Vaughan D, Girlich M (2024). tidyr: Tidy Messy Data. doi:10.32614/CRAN.package.tidyr https://doi.org/10.32614/CRAN.package.tidyr, R package version 1.3.1, https://CRAN.R-project.org/package=tidyr.

  • ggplot2 *

Wickham H (2016). ggplot2: Elegant Graphics for Data Analysis. Springer-Verlag New York. ISBN 978-3-319-24277-4, https://ggplot2.tidyverse.org.

  • knitr *

Xie Y (2025). knitr: A General-Purpose Package for Dynamic Report Generation in R. R package version 1.50, https://yihui.org/knitr/.

Xie Y (2015). Dynamic Documents with R and knitr, 2nd edition. Chapman and Hall/CRC, Boca Raton, Florida. ISBN 978-1498716963, https://yihui.org/knitr/.

Xie Y (2014). “knitr: A Comprehensive Tool for Reproducible Research in R.” In Stodden V, Leisch F, Peng RD (eds.), Implementing Reproducible Computational Research. Chapman and Hall/CRC. ISBN 978-1466561595.

  • rmarkdown *

Allaire J, Xie Y, Dervieux C, McPherson J, Luraschi J, Ushey K, Atkins A, Wickham H, Cheng J, Chang W, Iannone R (2024). rmarkdown: Dynamic Documents for R. R package version 2.29, https://github.com/rstudio/rmarkdown.

Xie Y, Allaire J, Grolemund G (2018). R Markdown: The Definitive Guide. Chapman and Hall/CRC, Boca Raton, Florida. ISBN 9781138359338, https://bookdown.org/yihui/rmarkdown.

Xie Y, Dervieux C, Riederer E (2020). R Markdown Cookbook. Chapman and Hall/CRC, Boca Raton, Florida. ISBN 9780367563837, https://bookdown.org/yihui/rmarkdown-cookbook.

Información de sesión

sessionInfo()
## R version 4.5.1 (2025-06-13 ucrt)
## Platform: x86_64-w64-mingw32/x64
## Running under: Windows 11 x64 (build 26200)
## 
## Matrix products: default
##   LAPACK version 3.12.1
## 
## locale:
## [1] LC_COLLATE=Spanish_Colombia.utf8  LC_CTYPE=Spanish_Colombia.utf8   
## [3] LC_MONETARY=Spanish_Colombia.utf8 LC_NUMERIC=C                     
## [5] LC_TIME=Spanish_Colombia.utf8    
## 
## time zone: America/Bogota
## tzcode source: internal
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
## [1] knitr_1.50    ggplot2_4.0.2 tidyr_1.3.1   dplyr_1.2.0  
## 
## loaded via a namespace (and not attached):
##  [1] vctrs_0.7.1        cli_3.6.5          rlang_1.1.7        xfun_0.52         
##  [5] purrr_1.2.1        generics_0.1.4     S7_0.2.1           jsonlite_2.0.0    
##  [9] labeling_0.4.3     glue_1.8.0         htmltools_0.5.8.1  sass_0.4.10       
## [13] scales_1.4.0       rmarkdown_2.29     grid_4.5.1         evaluate_1.0.4    
## [17] jquerylib_0.1.4    tibble_3.3.0       fastmap_1.2.0      yaml_2.3.10       
## [21] lifecycle_1.0.5    compiler_4.5.1     RColorBrewer_1.1-3 pkgconfig_2.0.3   
## [25] rstudioapi_0.17.1  farver_2.1.2       digest_0.6.37      R6_2.6.1          
## [29] tidyselect_1.2.1   pillar_1.11.0      magrittr_2.0.3     bslib_0.9.0       
## [33] withr_3.0.2        gtable_0.3.6       tools_4.5.1        cachem_1.1.0