# 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 <- "."
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).
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.
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.
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
clima1–clima6 y usamos las cuatro primeras
como predictores focales.
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.
# --- 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)
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)
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.
# 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.")
| 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.
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.
# 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.")
| 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.")
| 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.
# 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.
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.
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.
lme4::glmer) sería la mejora natural.| 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.
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).
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")
}
R Core Team (2025). R: A Language and Environment for Statistical Computing. R Foundation for Statistical Computing, Vienna, Austria. https://www.R-project.org/.
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.
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.
Wickham H (2016). ggplot2: Elegant Graphics for Data Analysis. Springer-Verlag New York. ISBN 978-3-319-24277-4, https://ggplot2.tidyverse.org.
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.
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.
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