Los archivos Salinidad.RData,
moluscos.RData y Biodiversidad.RData deben
estar en la misma carpeta que este
.Rmd.
library(tidyverse) # manejo de datos y ggplot2
library(car) # prueba de Levene
library(agricolae) # prueba LSD de Fisher
library(knitr) # tablas
library(patchwork) # combinar gráficos
theme_set(theme_minimal(base_size = 13) +
theme(plot.title = element_text(face = "bold"),
strip.text = element_text(face = "bold")))
colores <- c("#2C7FB8", "#D95F0E", "#31A354", "#756BB1")load("Salinidad.RData") # objeto: Salinidad
load("moluscos.RData") # objeto: BD_moluscos
load("Biodiversidad.RData") # objeto: BD_biodiversidadFunciones auxiliares que se usan en los tres puntos (resumen numérico, verificación de supuestos, gráficos de diagnóstico y tamaño de efecto):
# Resumen numérico de una variable
resumen_num <- function(x) {
tibble(n = sum(!is.na(x)), Media = mean(x), Mediana = median(x),
DE = sd(x), CV_pct = 100 * sd(x) / mean(x),
Min = min(x), Max = max(x))
}
# Shapiro-Wilk sobre residuales + Levene
supuestos <- function(modelo, formula, datos) {
sw <- shapiro.test(residuals(modelo))
lv <- leveneTest(formula, data = datos)
tibble(Prueba = c("Shapiro-Wilk (normalidad de residuales)",
"Levene (homogeneidad de varianzas)"),
`Estadístico` = round(c(unname(sw$statistic), lv$`F value`[1]), 3),
`Valor p` = format.pval(c(sw$p.value, lv$`Pr(>F)`[1]),
digits = 3, eps = 1e-4))
}
# QQ-plot de residuales y residuales vs. ajustados
diagnosticos <- function(modelo) {
d <- tibble(res = residuals(modelo), ajust = fitted(modelo))
p1 <- ggplot(d, aes(sample = res)) +
stat_qq(color = colores[1]) + stat_qq_line(color = colores[2]) +
labs(title = "QQ-plot de residuales",
x = "Cuantiles teóricos", y = "Cuantiles muestrales")
p2 <- ggplot(d, aes(ajust, res)) +
geom_point(color = colores[1]) +
geom_hline(yintercept = 0, linetype = "dashed", color = colores[2]) +
labs(title = "Residuales vs. ajustados",
x = "Valores ajustados", y = "Residuales")
p1 + p2
}
# Tamaño de efecto: eta cuadrado por término
eta2 <- function(modelo) {
tab <- summary(modelo)[[1]]
ss <- tab$`Sum Sq`
tibble(`Término` = trimws(rownames(tab)), `Eta²` = round(ss / sum(ss), 3))
}Se midieron 45 muestras de suelo en las que crece una planta forrajera natural. La respuesta es la biomasa (g) y las covariables son pH, salinidad, zinc y potasio.
Salinidad %>%
pivot_longer(everything(), names_to = "Variable", values_to = "valor") %>%
group_by(Variable) %>%
summarise(resumen_num(valor), .groups = "drop") %>%
kable(digits = 2, caption = "Resumen descriptivo de las variables (n = 45)")| Variable | n | Media | Mediana | DE | CV_pct | Min | Max |
|---|---|---|---|---|---|---|---|
| Biomasa | 45 | 1082.17 | 991.83 | 546.29 | 50.48 | 369.82 | 2337.33 |
| Potasio | 45 | 797.38 | 773.30 | 297.58 | 37.32 | 350.73 | 1441.67 |
| Salinidad | 45 | 30.27 | 30.00 | 3.72 | 12.29 | 24.00 | 38.00 |
| Zinc | 45 | 17.83 | 19.24 | 8.27 | 46.40 | 0.21 | 31.29 |
| pH | 45 | 4.61 | 4.45 | 1.25 | 27.22 | 3.20 | 7.45 |
Salinidad %>%
pivot_longer(everything(), names_to = "Variable", values_to = "valor") %>%
ggplot(aes(valor)) +
geom_histogram(aes(y = after_stat(density)), bins = 12,
fill = colores[1], color = "white", alpha = .85) +
geom_density(color = colores[2], linewidth = 1) +
facet_wrap(~Variable, scales = "free", ncol = 2) +
labs(title = "Distribución de cada característica",
x = NULL, y = "Densidad")Salinidad %>%
pivot_longer(everything(), names_to = "Variable", values_to = "valor") %>%
ggplot(aes(y = valor)) +
geom_boxplot(fill = colores[1], alpha = .6, width = .5) +
facet_wrap(~Variable, scales = "free", nrow = 1) +
labs(title = "Diagramas de caja", y = NULL) +
theme(axis.text.x = element_blank())Interpretación. La biomasa es muy variable (media ≈ 1082 g, DE ≈ 546 g, CV ≈ 50 %) y tiene asimetría positiva: la media supera a la mediana (≈ 992 g), de modo que pocas muestras muy productivas alargan la cola derecha. El pH (media ≈ 4.6) también es asimétrico a la derecha; la mayoría de los suelos son ácidos (mediana 4.45) y solo unos pocos superan pH 6. La salinidad es la más homogénea (CV ≈ 12 %, entre 24 y 38) y aproximadamente simétrica. El zinc (CV ≈ 46 %) muestra asimetría negativa, con unos pocos suelos con concentraciones muy bajas. El potasio varía entre ≈ 350 y 1440 con una ligera asimetría positiva. Que la biomasa sea asimétrica y su dispersión aumente con la media anticipa problemas de homogeneidad de varianzas más adelante.
Se mide la relación entre la biomasa y pH, salinidad y zinc (el potasio se incluye solo como referencia).
Salinidad %>%
pivot_longer(c(pH, Salinidad, Zinc, Potasio),
names_to = "Covariable", values_to = "valor") %>%
group_by(Covariable) %>%
summarise(`r de Pearson` = cor(valor, Biomasa),
`R²` = cor(valor, Biomasa)^2,
`rho de Spearman` = cor(valor, Biomasa, method = "spearman"),
.groups = "drop") %>%
arrange(desc(abs(`r de Pearson`))) %>%
kable(digits = 3, caption = "Asociación de cada covariable con la biomasa")| Covariable | r de Pearson | R² | rho de Spearman |
|---|---|---|---|
| pH | 0.928 | 0.861 | 0.878 |
| Zinc | -0.781 | 0.611 | -0.625 |
| Potasio | -0.073 | 0.005 | 0.102 |
| Salinidad | -0.067 | 0.004 | -0.157 |
largo <- Salinidad %>%
select(Biomasa, pH, Salinidad, Zinc) %>%
pivot_longer(-Biomasa, names_to = "Covariable", values_to = "valor")
cors <- largo %>% group_by(Covariable) %>%
summarise(r = cor(valor, Biomasa), .groups = "drop")
ggplot(largo, aes(valor, Biomasa)) +
geom_point(color = colores[1], alpha = .8, size = 2) +
geom_smooth(method = "lm", color = colores[2], fill = "#FDAE6B") +
geom_text(data = cors, inherit.aes = FALSE,
aes(x = -Inf, y = Inf, label = paste0("r = ", round(r, 2))),
hjust = -.2, vjust = 1.6, fontface = "bold") +
facet_wrap(~Covariable, scales = "free_x") +
labs(title = "Biomasa vs. covariables del suelo",
x = NULL, y = "Biomasa (g)")## [1] -0.7204699
Interpretación. El pH es la covariable que presenta mayor relación con la biomasa (r ≈ +0.93; explica ≈ 86 % de su variabilidad lineal): suelos menos ácidos se asocian con más biomasa. Le sigue el zinc (r ≈ −0.78), con relación negativa: más zinc, menos biomasa. La salinidad prácticamente no se relaciona con la biomasa (r ≈ −0.07) en el rango observado. Como pH y zinc están correlacionados entre sí (r ≈ −0.72), parte del efecto aparente del zinc puede deberse al pH (en suelos más ácidos el zinc suele ser más soluble y disponible), por lo que no deben interpretarse como efectos independientes. Por lo tanto, la variable a categorizar en el literal (c) es el pH.
Se divide el pH en tres niveles con los terciles (cada nivel con la misma cantidad de muestras, 15 por grupo), de forma que la comparación tenga tamaños iguales.
cortes <- quantile(Salinidad$pH, probs = c(0, 1/3, 2/3, 1))
Salinidad <- Salinidad %>%
mutate(pH_cat = cut(pH, breaks = cortes, include.lowest = TRUE,
labels = c("Bajo", "Medio", "Alto")),
logBiomasa = log(Biomasa))
Salinidad %>%
group_by(pH_cat) %>%
summarise(n = n(), `pH mín` = min(pH), `pH máx` = max(pH),
Media = mean(Biomasa), Mediana = median(Biomasa),
DE = sd(Biomasa), CV_pct = 100 * sd(Biomasa) / mean(Biomasa)) %>%
kable(digits = 2, caption = "Biomasa (g) por nivel de pH")| pH_cat | n | pH mín | pH máx | Media | Mediana | DE | CV_pct |
|---|---|---|---|---|---|---|---|
| Bajo | 15 | 3.20 | 3.75 | 593.02 | 545.54 | 164.83 | 27.79 |
| Medio | 15 | 3.95 | 4.85 | 1048.11 | 1039.64 | 244.91 | 23.37 |
| Alto | 15 | 5.00 | 7.45 | 1605.39 | 1422.84 | 547.60 | 34.11 |
ggplot(Salinidad, aes(pH_cat, Biomasa, fill = pH_cat)) +
geom_boxplot(alpha = .7, outlier.shape = NA) +
geom_jitter(width = .1, alpha = .6) +
scale_fill_manual(values = colores[c(2, 3, 1)], guide = "none") +
labs(title = "Biomasa según nivel de pH", x = "Nivel de pH", y = "Biomasa (g)")## Df Sum Sq Mean Sq F value Pr(>F)
## pH_cat 2 7712683 3856342 29.89 8.45e-09 ***
## Residuals 42 5418235 129006
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
| Prueba | Estadístico | Valor p |
|---|---|---|
| Shapiro-Wilk (normalidad de residuales) | 0.973 | 0.374885 |
| Levene (homogeneidad de varianzas) | 8.675 | 0.000702 |
Los residuales son compatibles con la normalidad, pero la prueba de Levene rechaza la homogeneidad de varianzas (la desviación estándar pasa de ≈ 165 g en pH bajo a ≈ 548 g en pH alto). Como el ANOVA clásico asume varianzas iguales, no se interpreta el modelo sobre la biomasa original. Se aplica una transformación logarítmica, que estabiliza la varianza cuando la dispersión crece con la media.
## Df Sum Sq Mean Sq F value Pr(>F)
## pH_cat 2 7.154 3.577 40.81 1.42e-10 ***
## Residuals 42 3.681 0.088
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
| Término | Eta² |
|---|---|
| pH_cat | 0.66 |
| Residuals | 0.34 |
| Prueba | Estadístico | Valor p |
|---|---|---|
| Shapiro-Wilk (normalidad de residuales) | 0.979 | 0.578 |
| Levene (homogeneidad de varianzas) | 1.413 | 0.255 |
Con log(Biomasa) se cumplen ambos
supuestos (Shapiro-Wilk y Levene no rechazan), por lo que el
ANOVA es válido. Como verificación adicional, una prueba no paramétrica
que no necesita estos supuestos:
##
## Kruskal-Wallis rank sum test
##
## data: Biomasa by pH_cat
## Kruskal-Wallis chi-squared = 29.2, df = 2, p-value = 4.564e-07
##
## Study: modelo_log ~ "pH_cat"
##
## LSD t Test for logBiomasa
##
## Mean Square Error: 0.08763569
##
## pH_cat, means and individual ( 95 %) CI
##
## logBiomasa std r se LCL UCL Min Max
## Alto 7.322857 0.3608580 15 0.07643546 7.168604 7.477110 6.640242 7.756763
## Bajo 6.351728 0.2641536 15 0.07643546 6.197475 6.505981 5.913025 6.885014
## Medio 6.926945 0.2508216 15 0.07643546 6.772692 7.081198 6.342922 7.307387
## Q25 Q50 Q75
## Alto 7.089255 7.260407 7.692731
## Bajo 6.176084 6.301772 6.491777
## Medio 6.789658 6.946627 7.088730
##
## Alpha: 0.05 ; DF Error: 42
## Critical Value of t: 2.018082
##
## least Significant Difference: 0.2181467
##
## Treatments with the same letter are not significantly different.
##
## logBiomasa groups
## Alto 7.322857 a
## Medio 6.926945 b
## Bajo 6.351728 c
letras1 <- as.data.frame(lsd1$groups) %>%
rownames_to_column("pH_cat") %>%
left_join(Salinidad %>% group_by(pH_cat) %>%
summarise(ymax = max(Biomasa), .groups = "drop"),
by = "pH_cat")
Salinidad %>%
group_by(pH_cat) %>%
summarise(`Media geométrica (g)` = exp(mean(logBiomasa))) %>%
kable(digits = 1, caption = "Media geométrica de la biomasa (equivale a la media de log(Biomasa) en la escala original)")| pH_cat | Media geométrica (g) |
|---|---|
| Bajo | 573.5 |
| Medio | 1019.4 |
| Alto | 1514.5 |
ggplot(Salinidad, aes(pH_cat, Biomasa, fill = pH_cat)) +
geom_boxplot(alpha = .7, outlier.shape = NA) +
geom_jitter(width = .1, alpha = .5) +
geom_text(data = letras1, aes(y = ymax * 1.06, label = groups),
fontface = "bold", size = 6) +
scale_fill_manual(values = colores[c(2, 3, 1)], guide = "none") +
labs(title = "Biomasa por nivel de pH (letras distintas = diferencia significativa, LSD)",
x = "Nivel de pH", y = "Biomasa (g)")Conclusión del punto 1. El nivel de pH del suelo tiene un efecto altamente significativo sobre la biomasa (ANOVA sobre log-biomasa, p < 0.001; el nivel de pH explica ≈ 66 % de la variación, un efecto muy grande). El LSD muestra que los tres niveles difieren entre sí: la biomasa aumenta de forma escalonada de pH bajo (≈ 593 g) a medio (≈ 1048 g) y a alto (≈ 1605 g). En términos del problema, la planta forrajera produce mucho más en suelos menos ácidos, y pasar de un suelo muy ácido a uno moderadamente ácido ya casi duplica la biomasa. Esto concuerda con el análisis bivariado y es relevante para el manejo del suelo (por ejemplo, encalado en suelos muy ácidos). Al ser un estudio observacional, la relación es una asociación y no prueba causalidad.
Dos tipos de moluscos (A y B) se sometieron a tres concentraciones de agua de mar (100 %, 75 % y 50 %) y se midió el consumo de oxígeno por unidad de peso seco.
moluscos <- BD_moluscos %>%
mutate(c_agua = factor(c_agua, levels = c(100, 75, 50),
labels = c("100%", "75%", "50%")),
molusco = factor(molusco))moluscos %>% summarise(resumen_num(cons_o)) %>%
kable(digits = 2, caption = "Consumo de oxígeno (todas las observaciones)")| n | Media | Mediana | DE | CV_pct | Min | Max |
|---|---|---|---|---|---|---|
| 48 | 9.3 | 9.7 | 3.68 | 39.58 | 1.8 | 18.8 |
moluscos %>% count(molusco, c_agua) %>%
pivot_wider(names_from = c_agua, values_from = n) %>%
kable(caption = "Número de observaciones por combinación (diseño balanceado)")| molusco | 100% | 75% | 50% |
|---|---|---|---|
| A | 8 | 8 | 8 |
| B | 8 | 8 | 8 |
p1 <- ggplot(moluscos, aes(cons_o)) +
geom_histogram(aes(y = after_stat(density)), bins = 10,
fill = colores[1], color = "white", alpha = .85) +
geom_density(color = colores[2], linewidth = 1) +
labs(title = "Consumo de oxígeno", x = "Consumo de O2 / peso seco", y = "Densidad")
p2 <- ggplot(moluscos, aes(y = cons_o)) +
geom_boxplot(fill = colores[1], alpha = .6, width = .4) +
labs(title = "Diagrama de caja", y = NULL) +
theme(axis.text.x = element_blank())
p1 + p2 + plot_layout(widths = c(2, 1))Interpretación. El consumo de oxígeno tiene una media de ≈ 9.3 y mediana ≈ 9.7 (DE ≈ 3.7, CV ≈ 40 %), con una distribución aproximadamente simétrica entre 1.8 y 18.8. Hay variabilidad considerable entre individuos, y los valores altos (> 14) son poco frecuentes pero no extremos. El diseño es balanceado: 8 individuos por cada combinación de molusco y concentración (48 en total), lo que facilita el análisis.
moluscos %>%
group_by(molusco, c_agua) %>%
summarise(n = n(), Media = mean(cons_o), Mediana = median(cons_o),
DE = sd(cons_o), .groups = "drop") %>%
kable(digits = 2, caption = "Consumo de oxígeno por tipo de molusco y concentración")| molusco | c_agua | n | Media | Mediana | DE |
|---|---|---|---|---|---|
| A | 100% | 8 | 9.94 | 9.30 | 2.75 |
| A | 75% | 8 | 7.89 | 7.18 | 2.74 |
| A | 50% | 8 | 12.18 | 11.11 | 3.09 |
| B | 100% | 8 | 7.41 | 6.14 | 2.84 |
| B | 75% | 8 | 6.10 | 5.60 | 2.74 |
| B | 50% | 8 | 12.33 | 12.85 | 3.52 |
moluscos %>% group_by(c_agua) %>%
summarise(Media = mean(cons_o), DE = sd(cons_o)) %>%
kable(digits = 2, caption = "Por concentración (ambos moluscos)")| c_agua | Media | DE |
|---|---|---|
| 100% | 8.67 | 3.0 |
| 75% | 6.99 | 2.8 |
| 50% | 12.25 | 3.2 |
g1 <- ggplot(moluscos, aes(c_agua, cons_o, fill = molusco)) +
geom_boxplot(alpha = .75, position = position_dodge(.8)) +
scale_fill_manual(values = colores[1:2], name = "Molusco") +
labs(title = "Consumo de O2 por concentración y tipo",
x = "Concentración de agua de mar", y = "Consumo de O2 / peso seco")
g2 <- moluscos %>%
group_by(molusco, c_agua) %>%
summarise(m = mean(cons_o), se = sd(cons_o) / sqrt(n()), .groups = "drop") %>%
ggplot(aes(c_agua, m, color = molusco, group = molusco)) +
geom_line(linewidth = 1) + geom_point(size = 3) +
geom_errorbar(aes(ymin = m - se, ymax = m + se), width = .12) +
scale_color_manual(values = colores[1:2], name = "Molusco") +
labs(title = "Gráfico de interacción (media ± EE)",
x = "Concentración de agua de mar", y = "Consumo medio de O2")
g1 + g2Interpretación. El consumo de oxígeno no cambia de forma lineal con la concentración: es mayor al 50 % (≈ 12.3), menor al 75 % (≈ 7.0) y intermedio al 100 % (≈ 8.7). Las conclusiones son similares para ambos moluscos: las dos curvas siguen el mismo patrón en forma de “V” (alto en 50 %, mínimo en 75 %), con líneas casi paralelas. El molusco A consume algo más que el B en 100 % y 75 %, pero en 50 % ambos consumen prácticamente lo mismo (≈ 12.2 vs. 12.3). La dispersión dentro de cada grupo es considerable, de modo que hace falta el ANOVA para juzgar qué diferencias son reales.
| Prueba | Estadístico | Valor p |
|---|---|---|
| Shapiro-Wilk (normalidad de residuales) | 0.958 | 0.0857 |
| Levene (homogeneidad de varianzas) | 0.172 | 0.9715 |
Los residuales no rechazan normalidad (el valor p de Shapiro-Wilk queda por encima de 0.05) y Levene no rechaza la homogeneidad de varianzas (p ≈ 0.97). Se cumplen los supuestos y el ANOVA clásico es apropiado.
## Df Sum Sq Mean Sq F value Pr(>F)
## molusco 1 23.2 23.23 2.651 0.111
## c_agua 2 230.8 115.41 13.171 3.63e-05 ***
## molusco:c_agua 2 15.4 7.68 0.876 0.424
## Residuals 42 368.0 8.76
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
| Término | Eta² |
|---|---|
| molusco | 0.036 |
| c_agua | 0.362 |
| molusco:c_agua | 0.024 |
| Residuals | 0.577 |
Como la interacción no es significativa, la lectura principal se hace sobre los efectos principales; se hace LSD para la concentración de agua (el único factor significativo). Como complemento se presenta el LSD entre las seis combinaciones.
##
## Study: modelo2 ~ "c_agua"
##
## LSD t Test for cons_o
##
## Mean Square Error: 8.762171
##
## c_agua, means and individual ( 95 %) CI
##
## cons_o std r se LCL UCL Min Max Q25 Q50
## 100% 8.67125 3.000940 16 0.7400241 7.177821 10.164679 3.68 14.0 6.140 8.595
## 50% 12.25062 3.199643 16 0.7400241 10.757196 13.744054 6.38 18.8 10.085 11.455
## 75% 6.99250 2.804093 16 0.7400241 5.499071 8.485929 1.80 13.2 5.200 6.430
## Q75
## 100% 10.5750
## 50% 14.5000
## 75% 8.7675
##
## Alpha: 0.05 ; DF Error: 42
## Critical Value of t: 2.018082
##
## least Significant Difference: 2.112028
##
## Treatments with the same letter are not significantly different.
##
## cons_o groups
## 50% 12.25062 a
## 100% 8.67125 b
## 75% 6.99250 b
moluscos <- moluscos %>% mutate(tratamiento = interaction(molusco, c_agua))
modelo2_trat <- aov(cons_o ~ tratamiento, data = moluscos)
lsd2_trat <- LSD.test(modelo2_trat, "tratamiento", console = TRUE)##
## Study: modelo2_trat ~ "tratamiento"
##
## LSD t Test for cons_o
##
## Mean Square Error: 8.762171
##
## tratamiento, means and individual ( 95 %) CI
##
## cons_o std r se LCL UCL Min Max Q25
## A.100% 9.93625 2.747976 8 1.046552 7.824222 12.048278 6.78 14.00 7.9850
## A.50% 12.17500 3.090178 8 1.046552 10.062972 14.287028 9.74 18.80 10.3100
## A.75% 7.89000 2.739578 8 1.046552 5.777972 10.002028 5.20 13.20 6.0775
## B.100% 7.40625 2.844076 8 1.046552 5.294222 9.518278 3.68 11.60 5.7225
## B.50% 12.32625 3.517909 8 1.046552 10.214222 14.438278 6.38 17.70 10.0575
## B.75% 6.09500 2.739108 8 1.046552 3.982972 8.207028 1.80 9.96 4.8300
## Q50 Q75
## A.100% 9.295 11.7250
## A.50% 11.110 12.5000
## A.75% 7.180 8.8925
## B.100% 6.140 10.1000
## B.50% 12.850 14.5000
## B.75% 5.595 7.3425
##
## Alpha: 0.05 ; DF Error: 42
## Critical Value of t: 2.018082
##
## least Significant Difference: 2.986858
##
## Treatments with the same letter are not significantly different.
##
## cons_o groups
## B.50% 12.32625 a
## A.50% 12.17500 a
## A.100% 9.93625 ab
## A.75% 7.89000 bc
## B.100% 7.40625 bc
## B.75% 6.09500 c
letras2 <- as.data.frame(lsd2$groups) %>%
rownames_to_column("c_agua") %>%
left_join(moluscos %>% group_by(c_agua) %>%
summarise(ymax = max(cons_o), .groups = "drop"), by = "c_agua")
ggplot(moluscos, aes(c_agua, cons_o, fill = c_agua)) +
geom_boxplot(alpha = .7, outlier.shape = NA) +
geom_jitter(aes(shape = molusco), width = .12, alpha = .7, size = 2) +
geom_text(data = letras2, aes(y = ymax * 1.07, label = groups),
fontface = "bold", size = 6) +
scale_fill_manual(values = colores[c(1, 3, 2)], guide = "none") +
labs(title = "Consumo de O2 por concentración (letras distintas = diferencia, LSD)",
x = "Concentración de agua de mar", y = "Consumo de O2 / peso seco",
shape = "Molusco")Conclusión del punto 2. Interacción (molusco × concentración): no es significativa (p ≈ 0.42), es decir, el efecto de la concentración de agua de mar es el mismo para los dos tipos de molusco y viceversa. Tipo de molusco: no tiene un efecto principal significativo (p ≈ 0.11); A consume en promedio algo más que B (≈ 10.0 vs. 8.6) pero la diferencia no se puede distinguir de la variación natural. Concentración de agua de mar: efecto altamente significativo (p < 0.001), explica ≈ 36 % de la variación total. Según el LSD, el consumo al 50 % es mayor que al 100 % y al 75 %, mientras que 100 % y 75 % no difieren entre sí. Biológicamente, el mayor consumo de oxígeno en agua más diluida es consistente con un mayor costo energético para mantener el equilibrio osmótico (osmorregulación) cuando el medio es hipotónico, y esto ocurre de forma similar en ambos moluscos. El mínimo observado en 75 % (menor que en 100 %) no es estadísticamente distinguible del de 100 %, así que no debe interpretarse como una tendencia real.
Se evalúa el efecto del uso del suelo sobre la biodiversidad de anfibios en una reserva forestal: 52 parcelas (13 por hábitat) en un gradiente de intervención antrópica.
bio <- BD_biodiversidad %>%
mutate(Habitat = factor(Habitat,
levels = c("Bosque primario", "Bosque secundario",
"Sistema silvopastoril", "Potrero")))bio %>%
select(Riqueza, Shannon, Altitud) %>%
pivot_longer(everything(), names_to = "Variable", values_to = "valor") %>%
group_by(Variable) %>%
summarise(resumen_num(valor), .groups = "drop") %>%
kable(digits = 2, caption = "Resumen descriptivo (52 parcelas)")| Variable | n | Media | Mediana | DE | CV_pct | Min | Max |
|---|---|---|---|---|---|---|---|
| Altitud | 52 | 1243.89 | 1254.80 | 172.71 | 13.88 | 950.90 | 1600.80 |
| Riqueza | 52 | 9.73 | 9.50 | 4.37 | 44.92 | 2.00 | 21.00 |
| Shannon | 52 | 1.76 | 1.85 | 0.61 | 34.44 | 0.67 | 2.98 |
bio %>%
select(Riqueza, Shannon, Altitud) %>%
pivot_longer(everything(), names_to = "Variable", values_to = "valor") %>%
ggplot(aes(valor)) +
geom_histogram(aes(y = after_stat(density)), bins = 12,
fill = colores[3], color = "white", alpha = .85) +
geom_density(color = colores[2], linewidth = 1) +
facet_wrap(~Variable, scales = "free", ncol = 2) +
labs(title = "Distribución de riqueza, diversidad de Shannon y altitud",
x = NULL, y = "Densidad")Interpretación. La riqueza promedio es ≈ 9.7 especies por parcela (DE ≈ 4.4), con un máximo de 21. El índice de Shannon promedia ≈ 1.76 (DE ≈ 0.61; rango 0.67 a 2.98), y la altitud ≈ 1244 m (DE ≈ 173 m; rango ≈ 951 a 1601 m). Estos valores mezclan cuatro hábitats con condiciones muy distintas, y ese contraste se explora en el literal (b).
bio %>%
group_by(Habitat) %>%
summarise(n = n(),
`Riqueza (media)` = mean(Riqueza), `Riqueza (DE)` = sd(Riqueza),
`Shannon (media)` = mean(Shannon), `Shannon (DE)` = sd(Shannon),
`Altitud (media)` = mean(Altitud), `Altitud (DE)` = sd(Altitud)) %>%
kable(digits = 2, caption = "Resumen por tipo de hábitat")| Habitat | n | Riqueza (media) | Riqueza (DE) | Shannon (media) | Shannon (DE) | Altitud (media) | Altitud (DE) |
|---|---|---|---|---|---|---|---|
| Bosque primario | 13 | 14.77 | 2.74 | 2.47 | 0.38 | 1453.19 | 77.50 |
| Bosque secundario | 13 | 11.08 | 3.01 | 1.97 | 0.22 | 1326.15 | 40.60 |
| Sistema silvopastoril | 13 | 8.08 | 2.50 | 1.60 | 0.28 | 1151.48 | 97.89 |
| Potrero | 13 | 5.00 | 1.29 | 1.00 | 0.24 | 1044.75 | 50.32 |
b1 <- ggplot(bio, aes(Habitat, Riqueza, fill = Habitat)) +
geom_boxplot(alpha = .75) + geom_jitter(width = .1, alpha = .5) +
scale_fill_manual(values = colores, guide = "none") +
labs(title = "Riqueza de especies", x = NULL, y = "Número de especies") +
theme(axis.text.x = element_text(angle = 20, hjust = 1))
b2 <- ggplot(bio, aes(Habitat, Shannon, fill = Habitat)) +
geom_boxplot(alpha = .75) + geom_jitter(width = .1, alpha = .5) +
scale_fill_manual(values = colores, guide = "none") +
labs(title = "Diversidad de Shannon", x = NULL, y = "Índice de Shannon") +
theme(axis.text.x = element_text(angle = 20, hjust = 1))
b1 + b2ggplot(bio, aes(Altitud, Shannon)) +
geom_point(aes(color = Habitat), size = 2.5, alpha = .85) +
geom_smooth(method = "lm", color = "black", se = FALSE, linewidth = 1) +
geom_smooth(aes(color = Habitat), method = "lm", se = FALSE,
linewidth = .6, linetype = "dashed") +
scale_color_manual(values = colores) +
labs(title = "Altitud vs. diversidad de Shannon",
subtitle = "Línea negra: todas las parcelas; líneas punteadas: dentro de cada hábitat",
x = "Altitud (m.s.n.m.)", y = "Índice de Shannon")## Correlación global Altitud-Shannon: 0.752
bio %>% group_by(Habitat) %>%
summarise(`r Altitud-Shannon` = cor(Altitud, Shannon), n = n()) %>%
kable(digits = 2, caption = "Correlación altitud-Shannon dentro de cada hábitat")| Habitat | r Altitud-Shannon | n |
|---|---|---|
| Bosque primario | -0.33 | 13 |
| Bosque secundario | -0.01 | 13 |
| Sistema silvopastoril | -0.51 | 13 |
| Potrero | 0.03 | 13 |
Interpretación. Tanto la riqueza como la diversidad de Shannon disminuyen de forma ordenada a lo largo del gradiente de intervención: bosque primario (riqueza ≈ 14.8; Shannon ≈ 2.47) > bosque secundario (≈ 11.1; 1.97) > sistema silvopastoril (≈ 8.1; 1.60) > potrero (≈ 5.0; 1.00). La dispersión dentro de cada hábitat es moderada y los hábitats se separan bastante bien. Respecto a la altitud, la correlación global con Shannon es alta (r ≈ 0.75), pero hay que ser cuidadoso: los hábitats también difieren en altitud (bosque primario ≈ 1453 m, potrero ≈ 1045 m), de modo que altitud y hábitat están confundidos. Al mirar dentro de cada hábitat la relación desaparece o incluso se vuelve negativa (r entre ≈ −0.5 y 0.03, con solo 13 parcelas por hábitat). Es decir, la asociación global se debe sobre todo a que los hábitats más conservados están ubicados a mayor altitud, y no a un efecto de la altitud en sí.
| Prueba | Estadístico | Valor p |
|---|---|---|
| Shapiro-Wilk (normalidad de residuales) | 0.978 | 0.463 |
| Levene (homogeneidad de varianzas) | 1.277 | 0.293 |
Ni Shapiro-Wilk ni Levene rechazan sus hipótesis nulas (p > 0.05): los residuales son compatibles con normalidad y las varianzas son homogéneas entre hábitats. El ANOVA clásico es apropiado.
## Df Sum Sq Mean Sq F value Pr(>F)
## Habitat 3 14.862 4.954 60.61 2.38e-16 ***
## Residuals 48 3.923 0.082
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
| Término | Eta² |
|---|---|
| Habitat | 0.791 |
| Residuals | 0.209 |
El ANOVA es significativo, por lo que se justifican las comparaciones múltiples.
##
## Study: modelo3 ~ "Habitat"
##
## LSD t Test for Shannon
##
## Mean Square Error: 0.08173622
##
## Habitat, means and individual ( 95 %) CI
##
## Shannon std r se LCL UCL Min
## Bosque primario 2.467692 0.3765668 13 0.07929314 2.3082628 2.627122 1.73
## Bosque secundario 1.974615 0.2204395 13 0.07929314 1.8151858 2.134045 1.44
## Potrero 1.003846 0.2396712 13 0.07929314 0.8444166 1.163276 0.67
## Sistema silvopastoril 1.603077 0.2812586 13 0.07929314 1.4436474 1.762506 1.14
## Max Q25 Q50 Q75
## Bosque primario 2.98 2.13 2.53 2.75
## Bosque secundario 2.27 1.86 2.03 2.10
## Potrero 1.34 0.80 0.98 1.20
## Sistema silvopastoril 2.06 1.41 1.62 1.86
##
## Alpha: 0.05 ; DF Error: 48
## Critical Value of t: 2.010635
##
## least Significant Difference: 0.2254674
##
## Treatments with the same letter are not significantly different.
##
## Shannon groups
## Bosque primario 2.467692 a
## Bosque secundario 1.974615 b
## Sistema silvopastoril 1.603077 c
## Potrero 1.003846 d
letras3 <- as.data.frame(lsd3$groups) %>%
rownames_to_column("Habitat") %>%
left_join(bio %>% group_by(Habitat) %>%
summarise(ymax = max(Shannon), .groups = "drop"), by = "Habitat") %>%
mutate(Habitat = factor(Habitat, levels = levels(bio$Habitat)))
ggplot(bio, aes(Habitat, Shannon, fill = Habitat)) +
geom_boxplot(alpha = .75, outlier.shape = NA) +
geom_jitter(width = .1, alpha = .5) +
geom_text(data = letras3, aes(y = ymax + .15, label = groups),
fontface = "bold", size = 6) +
scale_fill_manual(values = colores, guide = "none") +
labs(title = "Diversidad de Shannon por hábitat (letras distintas = diferencia, LSD)",
x = NULL, y = "Índice de Shannon") +
theme(axis.text.x = element_text(angle = 15, hjust = 1))Conclusión del punto 3. El tipo de hábitat tiene un efecto muy fuerte y significativo sobre la diversidad de Shannon (F ≈ 60.6, p < 0.001; el hábitat explica ≈ 79 % de la variación). El LSD indica que los cuatro hábitats difieren entre sí: bosque primario (≈ 2.47) > bosque secundario (≈ 1.97) > sistema silvopastoril (≈ 1.60) > potrero (≈ 1.00). La diversidad de anfibios cae de forma escalonada a medida que aumenta la intervención. El potrero conserva menos de la mitad de la diversidad del bosque primario, y el bosque secundario aún no recupera el nivel del primario. El sistema silvopastoril se comporta como un punto intermedio: mantiene más diversidad que el potrero (diferencia ≈ 0.6), lo que lo hace una opción de uso productivo menos dañina para los anfibios, aunque sin llegar al nivel del bosque. Por tratarse de un estudio observacional, y dado que la altitud difiere entre hábitats, el efecto del hábitat no puede separarse por completo del de la altitud.
## R version 4.5.2 (2025-10-31 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] patchwork_1.3.2 knitr_1.52 agricolae_1.3-7 car_3.1-5
## [5] carData_3.0-6 lubridate_1.9.5 forcats_1.0.1 stringr_1.6.0
## [9] dplyr_1.2.1 purrr_1.2.2 readr_2.1.6 tidyr_1.3.2
## [13] tibble_3.3.1 ggplot2_4.0.3 tidyverse_2.0.0
##
## loaded via a namespace (and not attached):
## [1] sass_0.4.10 generics_0.1.4 stringi_1.8.7 lattice_0.22-7
## [5] hms_1.1.4 digest_0.6.39 magrittr_2.0.4 evaluate_1.0.5
## [9] grid_4.5.2 timechange_0.4.0 RColorBrewer_1.1-3 fastmap_1.2.0
## [13] Matrix_1.7-4 jsonlite_2.0.0 Formula_1.2-6 mgcv_1.9-3
## [17] scales_1.4.0 jquerylib_0.1.4 abind_1.4-8 cli_3.6.5
## [21] rlang_1.1.7 splines_4.5.2 withr_3.0.2 cachem_1.1.0
## [25] yaml_2.3.12 otel_0.2.0 tools_4.5.2 AlgDesign_1.2.1.2
## [29] tzdb_0.5.0 vctrs_0.7.1 R6_2.6.1 lifecycle_1.0.5
## [33] MASS_7.3-65 cluster_2.1.8.1 pkgconfig_2.0.3 pillar_1.11.1
## [37] bslib_0.10.0 gtable_0.3.6 glue_1.8.0 xfun_0.56
## [41] tidyselect_1.2.1 rstudioapi_0.19.0 farver_2.1.2 htmltools_0.5.9
## [45] nlme_3.1-168 labeling_0.4.3 rmarkdown_2.30 compiler_4.5.2
## [49] S7_0.2.2