A continuación, se proporciona un script en R completo y comentado para realizar la exploración inicial (EDA) del dataset Soils del paquete carData, tal como se solicita en la Fase 1 de la actividad. Este código genera las visualizaciones clave (boxplots y perfil de medias) y además incluye resúmenes estadísticos y gráficos adicionales que ayudarán a los estudiantes a comprender la variabilidad del paisaje gilgai.

Puedes entregar este script a tus alumnos para que lo ejecuten en RStudio, o bien usarlo como base para que ellos lo adapten y amplíen en sus proyectos reproducibles.


# ============================================================================
# Script: EDA inicial del dataset "Soils" (carData)
# Asignatura: Diseño Experimental - Ingeniería Agrícola
# Objetivo: Visualizar la variabilidad del pH, fósforo (P) y densidad aparente
#           en función del contorno (Top, Slope, Depression) y la profundidad.
# ============================================================================

# 1. Cargar y verificar paquetes necesarios ----------------------------------
# Si no están instalados, descomentar las siguientes líneas:
# install.packages("carData")
# install.packages("tidyverse")
# install.packages("ggthemes")   # opcional para temas estéticos

library(carData)      # contiene el dataset Soils
library(tidyverse)    # manipulación y visualización (dplyr, ggplot2, etc.)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.2.1     ✔ readr     2.2.0
## ✔ forcats   1.0.1     ✔ stringr   1.6.0
## ✔ ggplot2   4.0.3     ✔ tibble    3.3.1
## ✔ lubridate 1.9.5     ✔ tidyr     1.3.2
## ✔ purrr     1.2.2     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(ggthemes)     # temas adicionales (opcional)

# 2. Cargar los datos y explorar su estructura --------------------------------
data("Soils")         # carga el dataset en el entorno
glimpse(Soils)        # vista rápida de tipos y primeros valores
## Rows: 48
## Columns: 14
## $ Group   <fct> 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6,…
## $ Contour <fct> Top, Top, Top, Top, Top, Top, Top, Top, Top, Top, Top, Top, To…
## $ Depth   <fct> 0-10, 0-10, 0-10, 0-10, 10-30, 10-30, 10-30, 10-30, 30-60, 30-…
## $ Gp      <fct> T0, T0, T0, T0, T1, T1, T1, T1, T3, T3, T3, T3, T6, T6, T6, T6…
## $ Block   <fct> 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1,…
## $ pH      <dbl> 5.40, 5.65, 5.14, 5.14, 5.14, 5.10, 4.70, 4.46, 4.37, 4.39, 4.…
## $ N       <dbl> 0.188, 0.165, 0.260, 0.169, 0.164, 0.094, 0.100, 0.112, 0.112,…
## $ Dens    <dbl> 0.92, 1.04, 0.95, 1.10, 1.12, 1.22, 1.52, 1.47, 1.07, 1.54, 1.…
## $ P       <int> 215, 208, 300, 248, 174, 129, 117, 170, 121, 115, 112, 117, 12…
## $ Ca      <dbl> 16.35, 12.25, 13.02, 11.92, 14.17, 8.55, 8.74, 9.49, 8.85, 4.7…
## $ Mg      <dbl> 7.65, 5.15, 5.68, 7.88, 8.12, 6.92, 8.16, 9.16, 10.35, 6.91, 7…
## $ K       <dbl> 0.72, 0.71, 0.68, 1.09, 0.70, 0.81, 0.39, 0.70, 0.74, 0.77, 0.…
## $ Na      <dbl> 1.14, 0.94, 0.60, 1.01, 2.17, 2.67, 3.32, 3.76, 5.74, 5.85, 5.…
## $ Conduc  <dbl> 1.09, 1.35, 1.41, 1.64, 1.85, 3.18, 4.16, 5.14, 5.73, 6.45, 8.…
summary(Soils)        # resumen estadístico de todas las variables
##      Group          Contour     Depth          Gp     Block        pH       
##  1      : 4   Depression:16   0-10 :12   D0     : 4   1:12   Min.   :3.740  
##  2      : 4   Slope     :16   10-30:12   D1     : 4   2:12   1st Qu.:4.058  
##  3      : 4   Top       :16   30-60:12   D3     : 4   3:12   Median :4.545  
##  4      : 4                   60-90:12   D6     : 4   4:12   Mean   :4.669  
##  5      : 4                              S0     : 4          3rd Qu.:5.140  
##  6      : 4                              S1     : 4          Max.   :6.670  
##  (Other):24                              (Other):24                         
##        N                Dens             P               Ca        
##  Min.   :0.03000   Min.   :0.780   Min.   : 79.0   Min.   : 3.820  
##  1st Qu.:0.05075   1st Qu.:1.127   1st Qu.:108.8   1st Qu.: 5.040  
##  Median :0.08450   Median :1.400   Median :131.0   Median : 7.305  
##  Mean   :0.10194   Mean   :1.316   Mean   :166.2   Mean   : 8.029  
##  3rd Qu.:0.12925   3rd Qu.:1.502   3rd Qu.:214.2   3rd Qu.: 9.735  
##  Max.   :0.29800   Max.   :1.600   Max.   :445.0   Max.   :16.350  
##                                                                    
##        Mg               K                Na             Conduc      
##  Min.   : 5.150   Min.   :0.1400   Min.   : 0.600   Min.   : 0.670  
##  1st Qu.: 7.537   1st Qu.:0.2750   1st Qu.: 2.545   1st Qu.: 2.790  
##  Median : 8.515   Median :0.4250   Median : 5.520   Median : 6.635  
##  Mean   : 8.465   Mean   :0.4662   Mean   : 5.600   Mean   : 6.589  
##  3rd Qu.: 9.648   3rd Qu.:0.6425   3rd Qu.: 8.355   3rd Qu.: 9.852  
##  Max.   :10.960   Max.   :1.0900   Max.   :11.040   Max.   :13.320  
## 
# Nota: Las variables son:
#   - Block   : factor (4 niveles) -> bloque experimental
#   - Contour : factor (3 niveles): Top, Slope, Depression
#   - Depth   : factor (4 niveles): 0-10, 10-30, 30-60, 60-90 cm
#   - pH, N, Dens, P, Ca, Mg, K, Na, Conduc : variables de respuesta (numéricas)

# 3. Gráfico de cajas (boxplot) para pH agrupado por Contour -----------------
# Muestra la distribución del pH en cada posición topográfica.
ggplot(Soils, aes(x = Contour, y = pH, fill = Contour)) +
  geom_boxplot(alpha = 0.7, outlier.shape = 21, outlier.fill = "red") +
  labs(
    title = "Variación del pH del suelo según el contorno del microrelieve",
    x = "Posición topográfica (Contour)",
    y = "pH del suelo",
    fill = "Contorno"
  ) +
  theme_minimal(base_size = 12) +
  theme(legend.position = "bottom") +
  scale_fill_brewer(palette = "Set2")

# 4. Gráfico de cajas para Fósforo (P) agrupado por Contour -----------------
# El fósforo es un nutriente crítico y su disponibilidad varía con el pH.
ggplot(Soils, aes(x = Contour, y = P, fill = Contour)) +
  geom_boxplot(alpha = 0.7, outlier.shape = 21, outlier.fill = "red") +
  labs(
    title = "Concentración de Fósforo (P) según el contorno del microrelieve",
    x = "Posición topográfica (Contour)",
    y = "Fósforo (ppm)",
    fill = "Contorno"
  ) +
  theme_minimal(base_size = 12) +
  theme(legend.position = "bottom") +
  scale_fill_brewer(palette = "Set2")

# 5. Perfil de medias: Densidad aparente (Dens) a través de la profundidad,
#    con líneas separadas para cada contorno ---------------------------------
# Este gráfico muestra cómo cambia la densidad aparente con la profundidad
# en las tres posiciones del microrelieve.
Soils_summary <- Soils %>%
  group_by(Contour, Depth) %>%
  summarise(
    mean_Dens = mean(Dens, na.rm = TRUE),
    sd_Dens   = sd(Dens, na.rm = TRUE),
    n         = n(),
    .groups   = "drop"
  )

# Convertir Depth a factor ordenado para mantener el orden en el eje x
Soils_summary$Depth <- factor(Soils_summary$Depth,
                              levels = c("0-10", "10-30", "30-60", "60-90"),
                              ordered = TRUE)

ggplot(Soils_summary, aes(x = Depth, y = mean_Dens, 
                          group = Contour, color = Contour)) +
  geom_line(linewidth = 1.2) +
  geom_point(size = 3, shape = 19) +
  # Barras de error (desviación estándar) para mostrar variabilidad
  geom_errorbar(aes(ymin = mean_Dens - sd_Dens, ymax = mean_Dens + sd_Dens),
                width = 0.2, alpha = 0.5) +
  labs(
    title = "Perfil de densidad aparente del suelo en función de la profundidad y el contorno",
    x = "Profundidad (cm)",
    y = "Densidad aparente (g/cm³)",
    color = "Contorno"
  ) +
  theme_minimal(base_size = 12) +
  theme(legend.position = "bottom") +
  scale_color_brewer(palette = "Set1")

# 6. Visualizaciones adicionales (opcionales) para un EDA más completo ------

# 6.1. Matriz de dispersión (pairs) para las variables químicas más relevantes
#      coloreada por Contour. Útil para detectar correlaciones.
pairs(Soils[, c("pH", "N", "P", "Ca", "Mg", "K", "Na", "Conduc")],
      col = c("red", "blue", "darkgreen")[as.numeric(Soils$Contour)],
      pch = 19, cex = 0.5,
      main = "Relaciones entre propiedades químicas del suelo (color = Contour)")

# 6.2. Histogramas de la densidad aparente y pH estratificados por Contour
ggplot(Soils, aes(x = Dens, fill = Contour)) +
  geom_histogram(bins = 15, alpha = 0.6, position = "identity") +
  facet_wrap(~ Contour) +
  labs(title = "Distribución de la densidad aparente por contorno",
       x = "Densidad aparente (g/cm³)", y = "Frecuencia") +
  theme_minimal() +
  scale_fill_brewer(palette = "Set2")

# 6.3. Diagrama de interacción para la variable pH entre Contour y Depth
#      (promedios) - similar al perfil pero para pH.
Soils_summary_pH <- Soils %>%
  group_by(Contour, Depth) %>%
  summarise(mean_pH = mean(pH, na.rm = TRUE), .groups = "drop")

Soils_summary_pH$Depth <- factor(Soils_summary_pH$Depth,
                                 levels = c("0-10", "10-30", "30-60", "60-90"),
                                 ordered = TRUE)

ggplot(Soils_summary_pH, aes(x = Depth, y = mean_pH, 
                             group = Contour, color = Contour)) +
  geom_line(linewidth = 1.2) +
  geom_point(size = 3) +
  labs(
    title = "Perfil de pH del suelo en función de la profundidad y el contorno",
    x = "Profundidad (cm)", y = "pH promedio",
    color = "Contorno"
  ) +
  theme_minimal(base_size = 12) +
  theme(legend.position = "bottom") +
  scale_color_brewer(palette = "Set1")

# 7. Guardar las gráficas en archivos (opcional) -----------------------------
# Si se desea exportar las imágenes para el informe:
# ggsave("boxplot_pH_Contour.png", plot = last_plot(), width = 8, height = 6)
# Nota: last_plot() guarda el último gráfico generado; es mejor asignar cada
#       gráfico a un objeto y luego guardarlo individualmente.

Explicación para los estudiantes

  1. Boxplots de pH y P: Permiten comparar visualmente la mediana, rango intercuartílico y valores atípicos de estas variables en las tres posiciones topográficas. Un pH más alto en las depresiones (Depression) podría indicar acumulación de sales o carbonatos, mientras que en las pendientes (Slope) o cimas (Top) puede ser más ácido por lixiviación.

  2. Perfil de densidad aparente: La densidad aparente tiende a aumentar con la profundidad por compactación natural, pero las diferencias entre contornos revelan el efecto del microrelieve: en las cimas, los ciclos de humedecimiento-secado compactan más el suelo; en las depresiones, la mayor humedad reduce la densidad.

  3. Gráficos adicionales:

    • La matriz de dispersión ayuda a identificar correlaciones (ej. pH vs Ca, o Na vs Conductividad).
    • Los histogramas por faceta muestran la forma de la distribución de cada variable en cada contorno.
    • Los perfiles de pH complementan el análisis de la profundidad.

Este script es el punto de partida para que los alumnos, en la Fase 1 de la actividad, generen las visualizaciones solicitadas y tomen apuntes en su cuaderno sobre las tendencias observadas. Luego, en fases posteriores, pasarán al análisis inferencial (ANOVA, MANOVA y contrastes polinómicos).