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 ...

Contexto

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).

a) Estadísticas descriptivas

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")
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.

b) Relación entre variables

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")
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.

c) Categorización del pH y análisis de varianza

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"
)
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")
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")
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)")
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)")
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)")
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")
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í.

Tabla resumen — Punto c)

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)")
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.

Conclusión General

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.