require(ggplot2)
require(agricolae)
require(car)
load("C:/Users/JULIANA/OneDrive/Documentos/UAO/SEXTO/DISEÑO/Salinidad.RData")
str(Salinidad)
## 'data.frame': 45 obs. of 5 variables:
## $ Biomasa : num 765 954 828 755 896 ...
## $ pH : num 5 4.7 4.2 4.4 5.55 5.5 4.25 4.45 4.75 4.6 ...
## $ Salinidad: int 33 35 32 30 33 33 36 30 38 30 ...
## $ Zinc : num 16.5 14 15.3 17.3 22.3 ...
## $ Potasio : num 1442 1299 1154 1045 522 ...
Para estudiar la relación entre ciertas características del suelo y la producción de biomasa (gr) de una planta forrajera natural se obtuvieron 45 muestras en diferentes ambientes, y en cada muestra se estimó la biomasa (respuesta Y) y se registraron las características (covariables X) del suelo en el que crecía (pH, Salinidad, Zinc y Potasio).
cv <- sapply(Salinidad, sd) / sapply(Salinidad, mean) * 100
df_desc <- data.frame(
Variable = names(Salinidad),
Media = round(sapply(Salinidad, mean), 2),
DE = round(sapply(Salinidad, sd), 2),
CV = round(cv, 1),
Mediana = round(sapply(Salinidad, median), 2),
Minimo = round(sapply(Salinidad, min), 2),
Maximo = round(sapply(Salinidad, max), 2)
)
colnames(df_desc) <- c("Variable", "Media", "DE", "CV (%)", "Mediana", "Mínimo", "Máximo")
knitr::kable(df_desc, row.names = FALSE, align = "c",
caption = "Tabla 1. Resumen de estadísticas descriptivas por variable")
| Variable | Media | DE | CV (%) | Mediana | Mínimo | Máximo |
|---|---|---|---|---|---|---|
| Biomasa | 1082.17 | 546.29 | 50.5 | 991.83 | 369.82 | 2337.33 |
| pH | 4.61 | 1.25 | 27.2 | 4.45 | 3.20 | 7.45 |
| Salinidad | 30.27 | 3.72 | 12.3 | 30.00 | 24.00 | 38.00 |
| Zinc | 17.83 | 8.27 | 46.4 | 19.24 | 0.21 | 31.29 |
| Potasio | 797.38 | 297.58 | 37.3 | 773.30 | 350.73 | 1441.67 |
Biomasa La biomasa presentó una media de 1080 g y una desviación estándar de 546 g, con valores entre 370 y 2340 g. El CV fue de 50.5% indicando una variabilidad relativamente alta entre las muestras. Mediana fue de 992 g.
pH El pH presentó una media de 4.61, desviación estándar de 1.25 y valores entre 3.2 y 7.45. Su coeficiente de variación fue de 27.2%. Mediana de 4.45.
Salinidad La salinidad presentó una media de 30.3, desviación estándar de 3.72 y un rango entre 24 y 38. El CV fue de 12.3%, siendo la variable con menor variabilidad relativa. Mediana de 30.
Zinc Presentó una media de 17.8, desviación estándar de 8.27 y valores entre 0.2011 y 31.3. Su CV fue de 46.4%, indicando una alta variabilidad relativa. Mediana de 19.2.
Potasio El potasio presentó una media de 797, desviación estándar de 298 y valores entre 351 y 1440. El CV fue de 37.3%, por lo que presentó una variabilidad relativa intermedia-alta. Mediana de 773.
par(mfrow = c(2,3))
hist(Salinidad$Biomasa, main="Biomasa", xlab="gr")
hist(Salinidad$pH, main="pH", xlab="pH")
hist(Salinidad$Salinidad, main="Salinidad", xlab="Salinidad")
hist(Salinidad$Zinc, main="Zinc", xlab="Zinc")
hist(Salinidad$Potasio, main="Potasio", xlab="Potasio")
Biomasa Media mayor a la mediana. Distribución asimétrica a la derecha (positiva). Una moda principal en 500-1500 y un grupito aparte en 2000-2500.
pH Media ligeramente mayor a la mediana, aunque la presencia de valores elevados entre aproximadamente 7.1 y 7.45 incrementa la dispersión y genera cierta asimetría. Asimetría positiva. Varias modas: una en 3-3.5, otra en 4.5-5 y un grupo en 7+.
Salinidad Media prácticamente igual a la mediana. Casi simétrica. Varias modas: una en 24-26, otra en 28-30 y en 34-36 (bimodal).
Zinc Media menor a la mediana. Asimetría negativa. Una moda en 15-25, con un grupito aparte cerca de 0.
Potasio Media un poco mayor a la mediana. Asimetría positiva (leve). Varias modas: 400-600, 800-1000 y 1200-1400.
par(mfrow = c(2,3))
boxplot(Salinidad$Biomasa,main="Biomasa")
boxplot(Salinidad$pH,main="pH")
boxplot(Salinidad$Salinidad, main="Salinidad")
boxplot(Salinidad$Zinc,main="Zinc")
boxplot(Salinidad$Potasio, main="Potasio")
par(mfrow = c(1,1))
Biomasa La mediana está casi en el centro de la caja, pero el bigote de arriba es mucho más largo que el de abajo. Indica asimetría positiva. No hay valores atípicos. Las muestras más altas están en el extremo del bigote.
pH La caja va de 3.45 a 5.35 y la mediana (4.45) está ubicada en medio. El bigote inferior es corto y el superior largo. Asimetría positiva. No hay valores atípicos.
Salinidad La mediana (30) queda justo en el centro de la caja y los bigotes son parecidos, el largo siendo un poco más largo. Es casi simétrica. Sin atípicos.
Zinc Mediana más cerca de Q3 que de Q1, bigote de abajo termina en 9.4. Sumado al punto suelto, indica asimetría negativa. Valor atípico que representa a cinco muestras (0.21 a 0.37). Forman un grupo con características propias y no errores de medición.
Potasio Bigote superior mucho más largo que el inferior. Asimetría positiva leve. Dentro de la caja, mediana un poco más cerca de Q3, así que las señales no son del todo claras. Sin atípicos.
R2 = cor(Salinidad[, c("Biomasa", "pH", "Salinidad", "Zinc", "Potasio")])^2
knitr::kable(round(R2, 3), align = "c",
caption = "Tabla 2. Matriz de R² entre las variables numéricas")
| Biomasa | pH | Salinidad | Zinc | Potasio | |
|---|---|---|---|---|---|
| Biomasa | 1.000 | 0.861 | 0.004 | 0.611 | 0.005 |
| pH | 0.861 | 1.000 | 0.002 | 0.519 | 0.001 |
| Salinidad | 0.004 | 0.002 | 1.000 | 0.182 | 0.000 |
| Zinc | 0.611 | 0.519 | 0.182 | 1.000 | 0.006 |
| Potasio | 0.005 | 0.001 | 0.000 | 0.006 | 1.000 |
pH: explica casi toda la variación de la biomasa.
Queda un 13.9% sin explicar, que es la dispersión de los puntos
alrededor de la recta.
Zinc: también explica
mucho, pero unos 25 puntos porcentuales menos que el pH.
Salinidad y potasio: explican menos del 1%. Con 45
muestras, un R² tan bajo no es significativo. No sirve para predecir la
biomasa.
ggplot(Salinidad, aes(x=pH, y=Biomasa)) + geom_point() + geom_smooth(method="lm")
pH vs Biomasa Los puntos siguen la
recta de cerca y el intervalo de confianza del 95% es angosto, es decir,
recta bien estimada de poca incertidumbre.
A mayor pH, mayor
biomasa.
El pH explica cerca del 86% de la biomasa (R²≈0.86),
este dato se confirma más abajo.
ggplot(Salinidad, aes(x=Zinc, y=Biomasa)) + geom_point() + geom_smooth(method="lm")
Zinc vs Biomasa La relación es
negativa: a más Zinc, menos biomasa. Su R²=0.61 es fuerte, pero más
dispersa que la del pH.
Entre Zinc 10 y 31 los puntos bajan con
más dispersión, y uno con Zinc ~20 y biomasa ~1890 destaca por
encima.
Parte de esta relación puede ser indirecta: pH y Zinc
están correlacionados entre sí (R²=-0.72), y son las mismas muestras en
el extremo. No se puede decir que el Zinc reduzca la biomasa. Solo que
ambas varían juntas.
ggplot(Salinidad, aes(x=Salinidad, y=Biomasa)) + geom_point() + geom_smooth(method="lm")
Salinidad vs Biomasa La recta es casi
horizontal y el intervalo de confianza es muy ancho. No se distingue el
cero.
Los puntos forman columnas verticales porque la salinidad
solo toma valores enteros. En cada columna hay biomasas muy distintas:
con salinidad 30, van de unos 370 a más de 2300 g.
La salinidad
no explica la biomasa en este conjunto de datos.
ggplot(Salinidad, aes(x=Potasio, y=Biomasa)) + geom_point() + geom_smooth(method="lm")
Potasio vs Biomasa Tampoco hay
tendencia: recta casi plana y banda ancha que incluye la
horizontal.
Se ven dos zonas: 5 puntos arriba a la izquierda
(Potasio ~450-570, biomasa mayor a 2100) y muchos abajo con biomasa baja
y Potasio parecido. Con Potasio ~500, la biomasa puede ser de 370 a 2337
g, así que el Potasio no sirve para predecirla.
if ("pH_cat" %in% names(Salinidad)) Salinidad$pH_cat = NULL
cortes = quantile(Salinidad$pH, probs = c(0, 1/3, 2/3, 1))
cortes
## 0% 33.33333% 66.66667% 100%
## 3.200000 3.883333 4.900000 7.450000
pH_cat = cut(Salinidad$pH, breaks = cortes, include.lowest = TRUE,
labels = c("Bajo", "Medio", "Alto"))
table(pH_cat)
## pH_cat
## Bajo Medio Alto
## 15 15 15
df_tabla3 <- data.frame(
`Categoría de pH` = c("Bajo", "Medio", "Alto"),
Media = round(tapply(Salinidad$Biomasa, pH_cat, mean), 2),
DE = round(tapply(Salinidad$Biomasa, pH_cat, sd), 2),
Mediana = round(tapply(Salinidad$Biomasa, pH_cat, median), 2),
Mínimo = round(tapply(Salinidad$Biomasa, pH_cat, min), 2),
Máximo = round(tapply(Salinidad$Biomasa, pH_cat, max), 2)
)
knitr::kable(
df_tabla3,
row.names = FALSE,
align = "c",
caption = "Tabla 3. Biomasa según categoría de pH"
)
| Categoría.de.pH | Media | DE | Mediana | Mínimo | Máximo |
|---|---|---|---|---|---|
| Bajo | 593.02 | 164.83 | 545.54 | 369.82 | 977.52 |
| Medio | 1048.11 | 244.91 | 1039.64 | 568.46 | 1491.28 |
| Alto | 1605.39 | 547.60 | 1422.84 | 765.28 | 2337.33 |
Biomasa según nivel de pH La biomasa
media aumenta escalonadamente con el nivel de pH.
En Bajo y
Medio la media y la mediana casi coinciden (distribuciones simétricas);
en Alto la media (1610) supera bastante a la mediana (1420), señal de
asimetría positiva, coherente con las 5 muestras extremas (biomasa >
2100) que tiene este grupo.
ggplot(Salinidad, aes(x=pH_cat, y=Biomasa, fill=pH_cat)) + geom_boxplot()
Boxplot por categoría de pH En el boxplot, las tres cajas casi no se traslapan y suben de izquierda a derecha. Bajo tiene un atípico leve (~978 g). La caja de Alto es mucho más ancha que las otras dos: va de ~1200 a ~2190, contra ~480-660 en Bajo y ~890-1200 en Medio. Esa diferencia de tamaño es la primera pista visual de que las varianzas no son iguales.
anova_sal = aov(Salinidad$Biomasa ~ pH_cat)
H0: las medias de biomasa son iguales en los tres
niveles de pH.
H1: al menos un nivel
difiere.
Como p<0.05, se rechaza H0: el nivel de pH genera
diferencias significativas en la biomasa.
tab_anova <- summary(anova_sal)[[1]]
df_anova <- data.frame(
Fuente = trimws(rownames(tab_anova)),
gl = tab_anova$Df,
SC = round(tab_anova$`Sum Sq`, 2),
CM = round(tab_anova$`Mean Sq`, 2),
F = round(tab_anova$`F value`, 3),
p_valor = signif(tab_anova$`Pr(>F)`, 4)
)
colnames(df_anova) <- c("Fuente", "gl", "SC", "CM", "F", "p-valor")
knitr::kable(df_anova, row.names = FALSE, align = "c",
caption = "Tabla 4. ANOVA de una vía — Biomasa según categoría de pH")
| Fuente | gl | SC | CM | F | p-valor |
|---|---|---|---|---|---|
| pH_cat | 2 | 7712683 | 3856341.6 | 29.893 | 0 |
| Residuals | 42 | 5418235 | 129005.6 | NA | NA |
df_dec_anova <- data.frame(
Prueba = "ANOVA de una vía",
H0 = "Las medias de biomasa son iguales en los tres niveles de pH",
H1 = "Al menos un nivel difiere",
Estadistico = round(tab_anova$`F value`[1], 3),
p_valor = signif(tab_anova$`Pr(>F)`[1], 4),
Decision = ifelse(tab_anova$`Pr(>F)`[1] < 0.05, "Se rechaza H0", "No se rechaza H0")
)
colnames(df_dec_anova) <- c("Prueba", "H0", "H1", "Estadístico F", "p-valor", "Decisión")
knitr::kable(df_dec_anova, row.names = FALSE, align = "c",
caption = "Tabla 5. Decisión — ANOVA de una vía")
| Prueba | H0 | H1 | Estadístico F | p-valor | Decisión |
|---|---|---|---|---|---|
| ANOVA de una vía | Las medias de biomasa son iguales en los tres niveles de pH | Al menos un nivel difiere | 29.893 | 0 | Se rechaza H0 |
shapiro_sal <- shapiro.test(residuals(anova_sal))
df_shapiro <- data.frame(
Prueba = "Shapiro-Wilk",
H0 = "Los residuales siguen una distribución normal",
Estadistico = round(shapiro_sal$statistic, 4),
p_valor = signif(shapiro_sal$p.value, 4),
Decision = ifelse(shapiro_sal$p.value < 0.05, "Se rechaza H0", "No se rechaza H0")
)
colnames(df_shapiro) <- c("Prueba", "H0", "Estadístico W", "p-valor", "Decisión")
knitr::kable(df_shapiro, row.names = FALSE, align = "c",
caption = "Tabla 6. Prueba de normalidad de los residuales (Shapiro-Wilk)")
| Prueba | H0 | Estadístico W | p-valor | Decisión |
|---|---|---|---|---|
| Shapiro-Wilk | Los residuales siguen una distribución normal | 0.9732 | 0.3749 | No se rechaza H0 |
H0: los residuales siguen una distribución
normal.
Como p>0.05, no se rechaza H0: el supuesto se cumple.
qqnorm(residuals(anova_sal)); qqline(residuals(anova_sal))
Q-Q Plot El Q-Qplot lo confirma: la mayoría de los puntos, sobre todo en el centro, sigue de cerca la recta. Hay una desviación leve en ambas colas (algunos puntos por debajo de la recta a la izquierda y por encima a la derecha), lo que indica colas un poco más pesadas que una normal perfecta, pero no lo suficiente como para que Shapiro lo detecte como anormal. Es un resultado coherente y no contradictorio.
bartlett_sal <- bartlett.test(Salinidad$Biomasa ~ pH_cat)
levene_sal <- leveneTest(Salinidad$Biomasa ~ pH_cat)
df_homog <- data.frame(
Prueba = c("Bartlett", "Levene"),
H0 = rep("Las varianzas de biomasa son iguales en los tres niveles de pH", 2),
Estadistico = c(round(bartlett_sal$statistic, 3), round(levene_sal$`F value`[1], 3)),
gl = c(paste(round(bartlett_sal$parameter, 2), collapse = ", "),
paste(levene_sal$Df, collapse = ", ")),
p_valor = c(signif(bartlett_sal$p.value, 4), signif(levene_sal$`Pr(>F)`[1], 4)),
Decision = c(ifelse(bartlett_sal$p.value < 0.05, "Se rechaza H0", "No se rechaza H0"),
ifelse(levene_sal$`Pr(>F)`[1] < 0.05, "Se rechaza H0", "No se rechaza H0"))
)
colnames(df_homog) <- c("Prueba", "H0", "Estadístico", "gl", "p-valor", "Decisión")
knitr::kable(df_homog, row.names = FALSE, align = "c",
caption = "Tabla 7. Pruebas de homogeneidad de varianzas (Bartlett y Levene)")
| Prueba | H0 | Estadístico | gl | p-valor | Decisión |
|---|---|---|---|---|---|
| Bartlett | Las varianzas de biomasa son iguales en los tres niveles de pH | 20.084 | 2 | 4.35e-05 | Se rechaza H0 |
| Levene | Las varianzas de biomasa son iguales en los tres niveles de pH | 8.675 | 2, 42 | 7.02e-04 | Se rechaza H0 |
H0: las tres varianzas son iguales.
Ambas
pruebas dan p<0.05, así que se rechaza H0 en las dos: el supuesto no
se cumple.
Que las dos pruebas coincidan le da más fuerza a la
conclusión: no es un artefacto de una sola prueba.
La causa se
ve en las DE: 165 (Bajo), 245 (Medio) y 548 (Alto). El grupo Alto es 3.3
veces más variable que Bajo, porque mezcla pH “normales” (5-5.6) con el
grupo aparte de pH mayor a 7 (biomasa 2160-2337).
welch_sal <- oneway.test(Salinidad$Biomasa ~ pH_cat)
df_welch <- data.frame(
Prueba = "Welch (ANOVA robusto a varianzas desiguales)",
H0 = "Las medias de biomasa son iguales en los tres niveles de pH",
Estadistico = round(welch_sal$statistic, 3),
gl_num = round(welch_sal$parameter[1], 2),
gl_den = round(welch_sal$parameter[2], 2),
p_valor = signif(welch_sal$p.value, 4),
Decision = ifelse(welch_sal$p.value < 0.05, "Se rechaza H0", "No se rechaza H0")
)
colnames(df_welch) <- c("Prueba", "H0", "Estadístico F", "gl num.", "gl denom.", "p-valor", "Decisión")
knitr::kable(df_welch, row.names = FALSE, align = "c",
caption = "Tabla 8. Prueba de Welch (ANOVA robusto)")
| Prueba | H0 | Estadístico F | gl num. | gl denom. | p-valor | Decisión |
|---|---|---|---|---|---|---|
| Welch (ANOVA robusto a varianzas desiguales) | Las medias de biomasa son iguales en los tres niveles de pH | 34.727 | 2 | 24.74 | 1e-07 | Se rechaza H0 |
El resultado confirma al ANOVA clásico que el pH afecta la biomasa.
lsd_sal <- LSD.test(anova_sal, "pH_cat", console = FALSE)
df_lsd <- data.frame(
Grupo = rownames(lsd_sal$groups),
Media = round(lsd_sal$groups[, 1], 2),
Letra = lsd_sal$groups$groups
)
knitr::kable(df_lsd, row.names = FALSE, align = "c",
caption = "Tabla 9. Prueba LSD — comparaciones múltiples de medias por nivel de pH")
| Grupo | Media | Letra |
|---|---|---|
| Alto | 1605.39 | a |
| Medio | 1048.11 | b |
| Bajo | 593.02 | c |
Letras distintas para los tres grupos significa que los tres niveles de pH difieren significativamente entre sí.
resumen_c <- data.frame(
Prueba = c("ANOVA (clásica)",
"Shapiro-Wilk (normalidad)",
"Bartlett (homocedasticidad)",
"Levene (homocedasticidad)",
"Welch (ANOVA robusto)"),
Estadistico = c(
round(tab_anova$`F value`[1], 3),
round(shapiro_sal$statistic, 4),
round(bartlett_sal$statistic, 3),
round(levene_sal$`F value`[1], 3),
round(welch_sal$statistic, 3)
),
p_valor = c(
signif(tab_anova$`Pr(>F)`[1], 4),
signif(shapiro_sal$p.value, 4),
signif(bartlett_sal$p.value, 4),
signif(levene_sal$`Pr(>F)`[1], 4),
signif(welch_sal$p.value, 4)
),
Decision = c(
ifelse(tab_anova$`Pr(>F)`[1] < 0.05, "Se rechaza H0", "No se rechaza H0"),
ifelse(shapiro_sal$p.value < 0.05, "Se rechaza H0", "No se rechaza H0"),
ifelse(bartlett_sal$p.value < 0.05, "Se rechaza H0", "No se rechaza H0"),
ifelse(levene_sal$`Pr(>F)`[1] < 0.05, "Se rechaza H0", "No se rechaza H0"),
ifelse(welch_sal$p.value < 0.05, "Se rechaza H0", "No se rechaza H0")
)
)
colnames(resumen_c) <- c("Prueba", "Estadístico", "p-valor", "Decisión")
knitr::kable(resumen_c, row.names = FALSE, align = "c",
caption = "Tabla 10. Todas las pruebas del punto c)")
| Prueba | Estadístico | p-valor | Decisión |
|---|---|---|---|
| ANOVA (clásica) | 29.8930 | 0.0000000 | Se rechaza H0 |
| Shapiro-Wilk (normalidad) | 0.9732 | 0.3749000 | No se rechaza H0 |
| Bartlett (homocedasticidad) | 20.0840 | 0.0000435 | Se rechaza H0 |
| Levene (homocedasticidad) | 8.6750 | 0.0007020 | Se rechaza H0 |
| Welch (ANOVA robusto) | 34.7270 | 0.0000001 | Se rechaza H0 |
En conjunto, las cinco pruebas cuentan la misma historia: el pH sí genera diferencias significativas en la biomasa (ANOVA y Welch), los residuales del ANOVA clásico se comportan como normales (Shapiro), pero el supuesto de varianzas iguales no se cumple (Bartlett y Levene) — por eso la prueba de Welch, que no exige varianzas iguales, es la más confiable para la conclusión final. La prueba LSD muestra además que los tres niveles de pH (Bajo, Medio, Alto) difieren entre sí en biomasa.
Los análisis desarrollados en este trabajo permitieron caracterizar la relación entre las propiedades del suelo y la producción de biomasa de la planta forrajera a partir de 45 muestras. El análisis exploratorio mostró diferencias importantes en la distribución y variabilidad de las variables. La biomasa presentó una variabilidad relativamente alta y cierta asimetría positiva, mientras que la salinidad mostró el comportamiento más homogéneo. El zinc y el potasio presentaron mayor variabilidad, con un grupo particular de valores bajos de zinc.
El análisis bivariado identificó al pH como la variable con mayor asociación con la biomasa, mostrando una relación positiva y un R² cercano a 0.86. El zinc también presentó una relación importante, aunque negativa, pero su asociación con el pH impide atribuirle un efecto independiente sobre la biomasa. Por otro lado, la salinidad y el potasio presentaron relaciones muy débiles y no mostraron capacidad relevante para explicar la variación de la biomasa en este conjunto de datos.
La categorización del pH mostró un aumento progresivo de la biomasa desde los niveles bajos hasta los altos, y el ANOVA confirmó que existen diferencias significativas entre las medias de los tres niveles de pH. Aunque los residuales cumplieron el supuesto de normalidad, las pruebas de Bartlett y Levene evidenciaron que las varianzas no son homogéneas, principalmente por la mayor variabilidad del grupo de pH alto. Por esta razón, la prueba de Welch resulta especialmente importante y confirmó que las diferencias entre los niveles de pH son significativas. Además, la prueba LSD mostró diferencias significativas entre los tres grupos.
En conjunto, los resultados muestran que, dentro de las variables estudiadas, el pH es la característica del suelo que presenta la asociación más fuerte con la producción de biomasa y que sus diferentes niveles se relacionan con diferencias significativas en la respuesta de la planta. Sin embargo, estos resultados representan asociaciones dentro de las muestras analizadas y no permiten afirmar que el pH, por sí solo, sea la causa directa del aumento de biomasa.