1 Contexto del Experimento.

La sección de contexto tiene como propósito informar a los lectores acerca del experimento: en qué consistió, dónde, cuándo y con que diseño se trabajó.

1.1 Ficha del Experimento.

# Lectura de la base original (todo como texto, para revisar cada valor tal como se escribió).
stopifnot(file.exists(params$archivo))
crudo <- as.data.frame(
  readxl::read_excel(params$archivo, sheet = 1, col_names = FALSE, col_types = "text"),
  stringsAsFactors = FALSE)

# Tu archivo viene con las variables en filas: si la primera celda es "grupo", se transpone.
if (tolower(trimws(crudo[1, 1])) == "grupo") {
  bruto <- as.data.frame(t(crudo[, -1]), stringsAsFactors = FALSE)
  rownames(bruto) <- NULL
} else {                                   # formato original de la plantilla
  bruto <- crudo[-1, ]
  if (all(is.na(bruto[[1]]))) bruto <- bruto[, -1]
}
stopifnot(ncol(bruto) >= 9)
bruto <- bruto[, 1:9]
names(bruto) <- c("grupo", "id_arbol", "lat", "lon", "n_hoja", "area_cm2",
                  "exposicion", "fecha", "observaciones")   # nombres exigidos por la guía
bruto <- bruto[!is.na(bruto$id_arbol), ]

# Recodificación de la exposición a las categorías de la guía (solo en R, el Excel no se toca).

fechas   <- as.Date(as.numeric(bruto$fecha), origin = "1899-12-30")
n_arbol  <- length(unique(toupper(trimws(bruto$id_arbol))))

ficha <- data.frame(
  Elemento = c("Pregunta", "Tipo de estudio", "Lugar", "Fecha de recolección",
               "Factor de interés", "Variable respuesta", "Unidad experimental",
               "Unidad de muestreo", "Tamaño de la muestra", "Instrumentos"),
  Descripción = c(
    "¿Cómo cambia el área de las hojas según el lugar donde crece el árbol?",
    "Observacional y comparativo: no se asignó sol o sombra; se eligieron árboles que ya estaban en cada condición",
    "Campus de la Universidad del Valle, sede Meléndez, Cali (Valle del Cauca, Colombia)",
    if (min(fechas) == max(fechas)) format(min(fechas), "%d/%m/%Y")
    else paste(format(min(fechas), "%d/%m/%Y"), "a", format(max(fechas), "%d/%m/%Y")),
    "Exposición del árbol a la luz: sol (luz directa la mayor parte del día), semisombra o sombra",
    "Área de la hoja en cm²",
    "El árbol (la exposición es una propiedad suya)",
    "La hoja: 10 hojas adultas y sanas por árbol",
    paste0("Grupo ", params$grupo, ": ", n_arbol, " árboles × 10 hojas; ", nrow(bruto), " filas registradas"),
    "Celular (cámara y GPS), papel blanco, lápiz y regla, y un script de Google Colab que calcula el área a partir de la foto"))
tabla(ficha, align = "ll")
Elemento Descripción
Pregunta ¿Cómo cambia el área de las hojas según el lugar donde crece el árbol?
Tipo de estudio Observacional y comparativo: no se asignó sol o sombra; se eligieron árboles que ya estaban en cada condición
Lugar Campus de la Universidad del Valle, sede Meléndez, Cali (Valle del Cauca, Colombia)
Fecha de recolección 22/10/2026
Factor de interés Exposición del árbol a la luz: sol (luz directa la mayor parte del día), semisombra o sombra
Variable respuesta Área de la hoja en cm²
Unidad experimental El árbol (la exposición es una propiedad suya)
Unidad de muestreo La hoja: 10 hojas adultas y sanas por árbol
Tamaño de la muestra Grupo 3: 5 árboles × 10 hojas; 50 filas registradas
Instrumentos Celular (cámara y GPS), papel blanco, lápiz y regla, y un script de Google Colab que calcula el área a partir de la foto

1.2 Sitio de Estudio y Protocolo

El estudio se realizó en el campus Meléndez de la Universidad del Valle (Cali), una zona tropical a ~1000 m s. n. m. con temperatura promedio de 24 °C y dos épocas de lluvia al año. La distribución de los árboles en el campus (en áreas abiertas, junto a construcciones o en parches de vegetación) ofreció un gradiente natural de luz durante la jornada, la cual presentó cielo nublado.

Fases del protocolo:

  • Selección y georreferenciación: Se eligieron 5 árboles adultos sanos de hojas simples y se registraron sus coordenadas por GPS.

  • Muestreo: Se recolectaron 10 hojas adultas e intactas por árbol, distribuidas en toda la copa.

  • Digitalización y análisis: Las hojas se trazaron en papel blanco y se fotografiaron junto a un marco de calibración de tamaño conocido para calcular su área mediante un script en Colab.

  • Registro: Los resultados se tabularon en la plantilla estandarizada del proyecto.

1.3 Mapa de Sitios

A continuación se presenta un mapa en el que se ubican los árboles muestreados. Cada punto en el mapa representa un árbol. Al hacer clic en cualquiera de ellos, se despliega sus datos registrados. El menú superior derecho permite alternar el mapa base (vías o imagen satelital) y filtrar la visualización por categorías. El uso de la vista satelital resulta fundamental para evaluar la exposición del árbol, ya que permite verificar si está totalmente expuesto a cielo abierto o bajo la sombra de otras copas.

niveles_expo <- c("sol", "semi", "sombra")
col_expo     <- c(sol = "#E69F00", semi = "#009E73", sombra = "#0072B2")
sitios$popup <- vapply(seq_len(nrow(sitios)), function(i) {
  s <- sitios[i, ]
  img <- if (is.na(s$foto)) "" else paste0("<img src='", knitr::image_uri(s$foto), "' width='200'><br>")
  paste0(img, "<b>", s$id_arbol, "</b><br>Exposición: ", s$exposicion, "<br>Hojas registradas: ",
         s$hojas, "<br>", fmt(s$lat, 5), "; ", fmt(s$lon, 5))
}, character(1))

presentes <- niveles_expo[niveles_expo %in% sitios$exposicion]

if (requireNamespace("leaflet", quietly = TRUE)) {
  library(leaflet)
  mapa <- leaflet() %>%
    addProviderTiles(providers$Esri.WorldImagery, group = "Satélite") %>%
    addTiles(group = "Calles")
  for (e in presentes) {
    d <- sitios[sitios$exposicion == e, ]
    mapa <- addCircleMarkers(mapa, data = d, lng = ~lon, lat = ~lat, radius = 9, weight = 2,
                             color = "white", fillColor = col_expo[[e]], fillOpacity = 0.95,
                             label = ~id_arbol, popup = ~popup,
                             popupOptions = popupOptions(maxWidth = 240), group = e)
  }
  mapa %>%
    addLayersControl(baseGroups = c("Satélite", "Calles"), overlayGroups = presentes,
                     options = layersControlOptions(collapsed = FALSE)) %>%
    addLegend("bottomright", colors = unname(col_expo[presentes]), labels = presentes,
              title = "Exposición", opacity = 1) %>%
    addScaleBar("bottomleft")
} else {
  cat("El paquete 'leaflet' no está instalado: se muestra un mapa simple.",
      "Para el mapa interactivo ejecuta install.packages('leaflet').\n")
  plot(sitios$lon, sitios$lat, pch = 21, cex = 3, bg = col_expo[sitios$exposicion],
       asp = 1 / cos(mean(sitios$lat) * pi / 180), xlab = "Longitud", ylab = "Latitud",
       main = "Ubicación de los árboles")
  text(sitios$lon, sitios$lat, sub(".*_", "", sitios$id_arbol), cex = 0.8)
  legend("topright", legend = presentes, pt.bg = col_expo[presentes], pch = 21, bty = "n")
}

1.4 Foto de los Árboles

Las fotos sirven para poder clasificar y evidenciar visiblemente los cambios de luz que sufren los árboles. A continuación se presentan las fotos de los árboles muestreados. Al hacer click se muestran los datos adicionales respectivos de cada árbol individualmente.

G1_T1
semi
G1_T1
Grupo: 1
Exposición: semi
Fecha: 22/10/2026
Coordenadas: 3,37750; -76,53417
Hojas medidas: 10
Área media: 12,63 cm² (DE 4,38)
Rango: 5,72 a 20,13 cm²
G2_T1
sol
G2_T1
Grupo: 2
Exposición: sol
Fecha: 22/10/2026
Coordenadas: 3,37750; -76,53361
Hojas medidas: 10
Área media: 83,95 cm² (DE 31,50)
Rango: 44,92 a 134,59 cm²
G3_T1
sombra
G3_T1
Grupo: 3
Exposición: sombra
Fecha: 22/10/2026
Coordenadas: 3,37750; -76,53444
Hojas medidas: 10
Área media: 26,84 cm² (DE 6,70)
Rango: 17,44 a 36,18 cm²
G1_T2
semi
G1_T2
Grupo: 4
Exposición: semi
Fecha: 22/10/2026
Coordenadas: 3,37722; -76,53528
Hojas medidas: 10
Área media: 13,93 cm² (DE 5,07)
Rango: 7,05 a 20,66 cm²
G3_T2
sombra
G3_T2
Grupo: 5
Exposición: sombra
Fecha: 22/10/2026
Coordenadas: 3,37694; -76,53528
Hojas medidas: 10
Área media: 27,63 cm² (DE 8,99)
Rango: 16,89 a 42,67 cm²

2 Introducción.

Como se mencionó en la sección pasada, la pregunta que se busca responder es ¿Cómo cambia el área de las hojas según el lugar donde crece el árbol?

Naturalmente lo que esperamos es que sí haya una diferencia con respecto al área foliar de las hojas. Esto debido a dos cosas principalmente: Las hojas funcionan bajo un equilibrio permanente: capturar la mayor cantidad de luz posible sin sobrecalentarse ni deshidratarse. En zonas expuestas a pleno sol, el principal reto es el calor y la pérdida de agua, por lo que las plantas desarrollan hojas más pequeñas. En cambio, a la sombra, la luz es escasa y una lámina foliar más amplia permite interceptar de manera eficiente la radiación disponible.

Por ende la hipótesis planteada es que las hojas de los árboles en ambientes donde reciben sombra la mayor parte del día presentarán un área foliar promedio mayor que las de árboles expuestos a pleno sol, registrando valores intermedios en condiciones de semisombra. Si la hipótesis es acertada, este patrón se reflejará de manera consistente al comparar los promedios entre los diferentes árboles y no como una variación aislada de un solo individuo.

\[\text{Área Foliar}_{\text{Sombra}} > \text{Área Foliar}_{\text{Semisombra}} > \text{Área Foliar}_{\text{Sol}}\]

3 Métodos.

Inicialmente el grupo seleccionó 5 árboles que estuvieran dentro del categoría Soleado, Sombreado o Semisombra (siendo este último una categoría añadida por las condiciones de los árboles). Fueron extraídas 10 hojas de distintas ramas de cada árbol, estas fueron elegidas sin algún daño aparente (hongo, forrajeo, etc).

Figura 1. Recolección de las hojas de G3_T1
(clic para ver la descripción)

La medición se llevó a cabo de la siguiente forma:

  1. Se realizó el trazo de la silueta de la hoja sobre papel.
  2. Se trazó un marco rectangular alrededor de la silueta; se toman las medidas de base y alto del marco.
  3. Se anotaron los datos en un script que calculó el área de las hojas en cm².
  4. Se anotaron los datos en la plantilla dada: una fila por hoja, cada una tiene grupo, árbol, coordenadas, número de hoja, área, exposición y fecha.
Figura 2. Pasos del proceso de medición
(clic para ver la descripción)

Y por último, se dividió el plan de análisis estadístico de la siguiente forma:

  1. Control de calidad de los datos. Se verificó la estructura del conjunto de datos y validación en inconsistencias.

  2. Estadística descriptiva para cada individuo. Se realizó el calculo de tamaño muestral (n), de las medidas de tendencia central (media y mediana para este caso), desviación estándar y coeficiente de variación (CV) para el área foliar de cada árbol.

  3. Visualización de datos. Se generaron gráficas descriptivas correspondientes a nivel de individuo y agrupadas por categorias de exposición.

  4. Detección e inspección de valores atípicos. Se identificaron observaciones extremas mediante el criterio del rango intercuartilico de Tukey, acompañada de una revisión cualitativa de los registros.

  5. Comparaciones entre niveles de exposición. Evaluación de las diferencias ambientales entre ambientes considerando los árboles como unidades experimentales, mediante el promedio de las 10 hojas por individuo.

  6. Modelación estadística y ANOVA.

    • Análisis de varianza (ANOVA) de un factor entre árboles con prueba de comparaciones múltiples de Tukey.

    • ANOVA anidado jerárquico (Hojas al interior de árbolesm anidados en exposición) para evaluar la partición de la varianza a diferentes niveles de organización.

4 Datos.

En esta sección se expondrán los datos obtenidos y la revisión de los mismos.

4.1 Datos en Bruto.

Inicialmente, se muestra a continuación los datos en bruto previo a realizar cálculos de los datos obtenidos.

grupo id_arbol lat lon n_hoja area_cm2 exposicion fecha observaciones
1 G1_T1 3,37750 -76,53417 1 19.63 Semisombra 22/10/2026
1 G1_T1 3,37750 -76,53417 2 11.61 Semisombra 22/10/2026
1 G1_T1 3,37750 -76,53417 3 10.94 Semisombra 22/10/2026
1 G1_T1 3,37750 -76,53417 4 10.73 Semisombra 22/10/2026
1 G1_T1 3,37750 -76,53417 5 13.22 Semisombra 22/10/2026
1 G1_T1 3,37750 -76,53417 6 13.35 Semisombra 22/10/2026
1 G1_T1 3,37750 -76,53417 7 9.51 Semisombra 22/10/2026
1 G1_T1 3,37750 -76,53417 8 11.51 Semisombra 22/10/2026
1 G1_T1 3,37750 -76,53417 9 5.72 Semisombra 22/10/2026
1 G1_T1 3,37750 -76,53417 10 20.13 Semisombra 22/10/2026
2 G2_T1 3,37750 -76,53361 1 47.61 Soleado 22/10/2026
2 G2_T1 3,37750 -76,53361 2 44.92 Soleado 22/10/2026
2 G2_T1 3,37750 -76,53361 3 91.92 Soleado 22/10/2026
2 G2_T1 3,37750 -76,53361 4 69.05 Soleado 22/10/2026
2 G2_T1 3,37750 -76,53361 5 120.23 Soleado 22/10/2026
2 G2_T1 3,37750 -76,53361 6 80.81 Soleado 22/10/2026
2 G2_T1 3,37750 -76,53361 7 55.48 Soleado 22/10/2026
2 G2_T1 3,37750 -76,53361 8 116.61 Soleado 22/10/2026
2 G2_T1 3,37750 -76,53361 9 134.59 Soleado 22/10/2026
2 G2_T1 3,37750 -76,53361 10 78.260000000000005 Soleado 22/10/2026
3 G3_T1 3,37750 -76,53444 1 36.18 Sombreado 22/10/2026
3 G3_T1 3,37750 -76,53444 2 23.23 Sombreado 22/10/2026
3 G3_T1 3,37750 -76,53444 3 30.8 Sombreado 22/10/2026
3 G3_T1 3,37750 -76,53444 4 32.75 Sombreado 22/10/2026
3 G3_T1 3,37750 -76,53444 5 17.440000000000001 Sombreado 22/10/2026
3 G3_T1 3,37750 -76,53444 6 33.74 Sombreado 22/10/2026
3 G3_T1 3,37750 -76,53444 7 27.23 Sombreado 22/10/2026
3 G3_T1 3,37750 -76,53444 8 19.63 Sombreado 22/10/2026
3 G3_T1 3,37750 -76,53444 9 18.93 Sombreado 22/10/2026
3 G3_T1 3,37750 -76,53444 10 28.43 Sombreado 22/10/2026
4 G1_T2 3,37722 -76,53528 1 7.05 Semisombra 22/10/2026
4 G1_T2 3,37722 -76,53528 2 8.18 Semisombra 22/10/2026
4 G1_T2 3,37722 -76,53528 3 20.66 Semisombra 22/10/2026
4 G1_T2 3,37722 -76,53528 4 13.14 Semisombra 22/10/2026
4 G1_T2 3,37722 -76,53528 5 18.12 Semisombra 22/10/2026
4 G1_T2 3,37722 -76,53528 6 18.920000000000002 Semisombra 22/10/2026
4 G1_T2 3,37722 -76,53528 7 12.26 Semisombra 22/10/2026
4 G1_T2 3,37722 -76,53528 8 19.88 Semisombra 22/10/2026
4 G1_T2 3,37722 -76,53528 9 11.36 Semisombra 22/10/2026
4 G1_T2 3,37722 -76,53528 10 9.6999999999999993 Semisombra 22/10/2026
5 G3_T2 3,37694 -76,53528 1 33.4 Sombreado 22/10/2026
5 G3_T2 3,37694 -76,53528 2 30.48 Sombreado 22/10/2026
5 G3_T2 3,37694 -76,53528 3 18.100000000000001 Sombreado 22/10/2026
5 G3_T2 3,37694 -76,53528 4 19.3 Sombreado 22/10/2026
5 G3_T2 3,37694 -76,53528 5 30.15 Sombreado 22/10/2026
5 G3_T2 3,37694 -76,53528 6 39.04 Sombreado 22/10/2026
5 G3_T2 3,37694 -76,53528 7 21.14 Sombreado 22/10/2026
5 G3_T2 3,37694 -76,53528 8 25.12 Sombreado 22/10/2026
5 G3_T2 3,37694 -76,53528 9 42.67 Sombreado 22/10/2026
5 G3_T2 3,37694 -76,53528 10 16.89 Sombreado 22/10/2026

La tabla expone las 50 filas necesarias (10 hojas por 5 árboles) tal como pide la guía.

4.2 Revisión de los datos.

Como se mencionó previamente, es necesario en primer lugar revisar la calidad de los datos antes de comenzar a hacer cálculos o análisis para corroborar que ningún error venga de los mismos. Para ello la siguiente tabla tiene como propósito verificar todo lo anteriormente mencionado.

Revisión Encontrado Estado Detalle
IDs que no siguen el formato G#_T# 0 ✔ Correcto —
Áreas vacías, no numéricas o ≤ 0 0 ✔ Correcto —
Exposiciones no reconocidas 0 ✔ Correcto —
Árboles con más de una exposición 0 ✔ Correcto —
Filas repetidas (mismo árbol y misma hoja) 0 ✔ Correcto —
Números de hoja fuera de 1 a 10 0 ✔ Correcto —
Árboles que no tienen exactamente 10 hojas 0 ✔ Correcto —
Fechas vacías o inválidas 0 ✔ Correcto —

Como se pudo observar, el conjunto de datos no presentó duplicados. Todos los registros correspondieron a valores de área foliar válidos (\(> 0\text{ cm}^2\)) y se verificó la secuencia completa de 1 a 10 hojas por individuo. Cada árbol quedó asociado unívocamente a una sola categoría de exposición solar. Dado que la totalidad de las muestras se recolectó y midió en la misma jornada y que el campo de observaciones no registró incidencias (hojas dañadas o trazos dudosos), se conservaron las 50 observaciones originales sin criterios de exclusión documentados.

5 Resultados.

5.1 Estadística Descriptiva.

cv <- function(x) 100 * sd(x) / mean(x)     # coeficiente de variación (%)

resumen <- do.call(rbind, lapply(split(datos, datos$id_arbol), function(d) {
  data.frame(arbol = d$id_arbol[1], exposicion = as.character(d$exposicion[1]), n = nrow(d),
             media = mean(d$area_cm2), mediana = median(d$area_cm2),
             de = sd(d$area_cm2), cv_pct = cv(d$area_cm2),
             minimo = min(d$area_cm2), maximo = max(d$area_cm2))
}))
resumen <- resumen[order(as.integer(sub(".*_T", "", resumen$arbol))), ]

tabla(resumen, row.names = FALSE, digits = c(0, 0, 0, 1, 1, 1, 1, 1, 1),
      col.names = c("Árbol", "Exposición", "n", "Media", "Mediana", "DE", "CV (%)", "Mín.", "Máx."),
      caption = "Área foliar (cm²) por árbol. DE = desviación estándar; CV = DE / media.")
Área foliar (cm²) por árbol. DE = desviación estándar; CV = DE / media.
Árbol Exposición n Media Mediana DE CV (%) Mín. Máx.
G1_T1 semi 10 12,6 11,6 4,4 34,6 5,7 20,1
G2_T1 sol 10 83,9 79,5 31,5 37,5 44,9 134,6
G3_T1 sombra 10 26,8 27,8 6,7 25,0 17,4 36,2
G1_T2 semi 10 13,9 12,7 5,1 36,4 7,0 20,7
G3_T2 sombra 10 27,6 27,6 9,0 32,6 16,9 42,7

De esta tabla se puede observar que las hojas de los árboles en sol fueron las de mayor área, con una media de 83,9 cm², frente a 26,8 y 27,6 cm² en sombra y 12,6 y 13,9 cm² en semisombra. Los dos árboles de cada una de estas últimas condiciones dieron valores muy parecidos entre sí, y los rangos de sol (44,9 a 134,6 cm²) quedaron por encima de todos los de sombra (máximo de 42,7 cm²). La variabilidad relativa fue similar en todos los árboles (CV entre 25 % y 37,5 %), y las medias se acercaron a las medianas, sin valores extremos que distorsionen el resultado.

5.2 Boxplot individual.

dg <- datos                                  # copia, para no alterar `datos`
oscurecer <- function(col, f = 0.6) {        # oscurece un color (para bordes y puntos)
  m <- col2rgb(col) / 255 * f
  rgb(m[1, ], m[2, ], m[3, ])
}
presentes <- niveles_expo[niveles_expo %in% resumen$exposicion]

dg$id_arbol <- factor(dg$id_arbol, levels = resumen$arbol)
par(mar = c(4.5, 4.8, 3, 1))
boxplot(area_cm2 ~ id_arbol, data = dg, outline = FALSE, las = 1,
        col = adjustcolor(col_expo[resumen$exposicion], 0.6), border = oscurecer(col_expo[resumen$exposicion]),
        lwd = 1.6, boxwex = 0.65,
        xlab = "Árbol", ylab = expression("Área foliar (cm"^2*")"),
        main = "Área foliar por árbol")
stripchart(area_cm2 ~ id_arbol, data = dg, vertical = TRUE, method = "jitter", jitter = 0.12,
           pch = 16, col = adjustcolor(oscurecer(col_expo[resumen$exposicion]), 0.8), add = TRUE)
legend("topleft", legend = presentes, fill = adjustcolor(col_expo[presentes], 0.55), bty = "n")

El boxplot indica un solapamiento casi perfecto entre las replicas de semisombra (G1_T1 y G1_T2) y de sombra (G3_T1 y G3_T2), mientras que el soleado (G2_T1) no se solapa y presenta valores significativamente superiores.

5.3 Valores atípicos.

El criterio de evaluación de observaciones atípicas (hojas con medidas “extremas”) se llevó a cabo mediante un protocolo de decisión en dos etapas:

  1. Evaluación de errores de medición o digitalización: Se verificó la presencia de inconsistencias técnicas (errores de unidad de medida, daños físicos no detectados en la lámina foliar, trazos imprecisos en la delimitación del área o fotografías borrosas). De identificarse alguna de estas causas, el valor fue corregido o excluido en la fase de control de calidad.

  2. Evaluación de variabilidad biológica (Regla de Tukey): En ausencia de errores técnicos, si el valor se ubicó fuera de los límites del rango intercuartílico por árbol (\(\text{Área} < Q_1 - 1.5 \times \text{IQR}\) o \(\text{Área} > Q_3 + 1.5 \times \text{IQR}\)), se consideró una variante biológica genuina. En consecuencia, la observación fue conservada en el conjunto de datos principal y su impacto potencial se evaluó mediante un análisis de sensibilidad (comparando los modelos con y sin dicha observación).

fuera <- do.call(rbind, lapply(split(datos, datos$id_arbol), function(d) {
  d[d$area_cm2 %in% boxplot.stats(d$area_cm2)$out,
    c("id_arbol", "exposicion", "n_hoja", "area_cm2", "observaciones")]
}))

if (is.null(fuera) || nrow(fuera) == 0) {
  cat("Ninguna hoja queda fuera de los límites de Tukey de su árbol.\n")
} else {
  fuera$observaciones[is.na(fuera$observaciones)] <- ""
  tabla(fuera, row.names = FALSE, digits = 2,
        col.names = c("Árbol", "Exposición", "Hoja", "Área (cm²)", "Observaciones"),
        caption = "Hojas fuera de los límites de Tukey de su árbol.")
}
Hojas fuera de los límites de Tukey de su árbol.
Árbol Exposición Hoja Área (cm²) Observaciones
G1_T1 semi 1 19,63
G1_T1 semi 9 5,72
G1_T1 semi 10 20,13
sens <- do.call(rbind, lapply(split(datos, datos$id_arbol), function(d) {
  out <- boxplot.stats(d$area_cm2)$out
  data.frame(arbol = d$id_arbol[1], exposicion = as.character(d$exposicion[1]),
             atipicas = length(out),
             media = mean(d$area_cm2), mediana = median(d$area_cm2),
             media_sin_atipicas = mean(d$area_cm2[!d$area_cm2 %in% out]))
}))
sens <- sens[order(as.integer(sub(".*_T", "", sens$arbol))), ]
tabla(sens, row.names = FALSE, digits = c(0, 0, 0, 1, 1, 1),
      col.names = c("Árbol", "Exposición", "Hojas atípicas", "Media (todas)", "Mediana", "Media sin atípicas"),
      caption = "Sensibilidad del resumen de cada árbol (cm²) a las hojas atípicas.")
Sensibilidad del resumen de cada árbol (cm²) a las hojas atípicas.
Árbol Exposición Hojas atípicas Media (todas) Mediana Media sin atípicas
G1_T1 semi 3 12,6 11,6 11,6
G2_T1 sol 0 83,9 79,5 83,9
G3_T1 sombra 0 26,8 27,8 26,8
G1_T2 semi 0 13,9 12,7 13,9
G3_T2 sombra 0 27,6 27,6 27,6

Con esto fue posible saber que tres hojas del árbol G1_T1 (Hojas #1, #9 y #10 con 19.6, 5.7 y 20.1 cm2) quedan fuera de los límites de Tukey dentro de este árbol; en otros árboles no hay hoja que quede por fuera. Respecto a si se debe a la causa de medición, no se encontró ningún error de medición en las hojas. Al ser un árbol de hojas pequeñas y poco variables (al menos en la zona muestreada), sus límites son estrechos y estas hojas pese a ser cercanas al resto, las sobrepasan. Quitar las hojas cambiaría la media de G1_T1 de 12,6 a 11,6 cm2, una diferencia pequeña en comparación a los otros árboles (13.9 cm2 en G1_T2 y más de 26 cm2 en sombra y sol). Decisión: se conservan todas las hojas.

5.4 Boxplot por Exposición.

# Orden y colores definidos aquí, para que no dependan de otros chunks
niveles_expo <- c("sol", "semi", "sombra")
col_expo     <- c(sol = "#E69F00", semi = "#009E73", sombra = "#0072B2")

dg <- datos                                  # copia, para no alterar `datos`
oscurecer <- function(col, f = 0.6) {        # oscurece un color (para bordes)
  m <- col2rgb(col) / 255 * f
  rgb(m[1, ], m[2, ], m[3, ])
}
presentes <- niveles_expo[niveles_expo %in% dg$exposicion]          # sol, semi, sombra
arboles   <- resumen$arbol
dg$id_arbol <- factor(dg$id_arbol, levels = arboles)

dg$expo <- factor(dg$exposicion, levels = presentes)
simbolos <- c(16, 17, 15, 18, 8)[seq_along(arboles)]
simbolo  <- simbolos[as.integer(dg$id_arbol)]
par(mar = c(4.5, 4.8, 3, 1))
boxplot(area_cm2 ~ expo, data = dg, outline = FALSE, las = 1,
        ylim = range(dg$area_cm2),   # que el eje incluya todas las hojas, también las más grandes
        col = adjustcolor(col_expo[presentes], 0.55), border = oscurecer(col_expo[presentes]),
        lwd = 1.6, boxwex = 0.6,
        xlab = "Exposición", ylab = expression("Área foliar (cm"^2*")"),
        main = "Árboles por exposición")
set.seed(2)   # para que la separación horizontal de los puntos sea siempre la misma
points(as.integer(dg$expo) + runif(nrow(dg), -0.15, 0.15), dg$area_cm2,
       pch = simbolo, col = adjustcolor("#1F2A24", 0.65))
legend("topright", legend = arboles, pch = simbolos, bty = "n",
       title = "Árbol", cex = 0.85)

En el boxplot se puede observar que las hojas de un mismo árbol se agrupan en el gráfico, por lo que no son observaciones independientes: la unidad de análisis es el árbol y no la hoja (pseudorreplicación). En sol hay un único árbol (G2_T1), así que su caja describe a ese individuo —mediana cercana a 80 cm² y gran dispersión— y no necesariamente a la condición de sol. En semi y sombra, en cambio, los dos árboles de cada condición se superponen, lo que indica resultados consistentes entre ellos: la sombra tuvo hojas mayores (mediana ≈ 28 cm²) que la semisombra (≈ 12 cm²). Al ser un estudio observacional con pocos árboles, estas diferencias son descriptivas y podrían deberse también a otros factores, como la especie.

5.5 El Árbol como Unidad de Análisis.

Dentro del trabajo realizado, a los que se les asigna la categoría de exposición son los árboles, no las hojas; las hojas de cada árbol comparten todas las características del mismo árbol. Es por esto que se promedian y se compara un valor único por árbol: realmente se desea es saber cuantos árboles hay por categoría.

dg <- datos 
medias_g <- aggregate(area_cm2 ~ id_arbol + exposicion, data = dg, FUN = mean)
medias_g$exposicion <- factor(medias_g$exposicion, levels = c("sol", "semi", "sombra"))
medias_g <- medias_g[order(medias_g$exposicion, medias_g$id_arbol), ]
medias_g <- medias_g[medias_g$area_cm2 > 0 & !is.na(medias_g$area_cm2), ]

tabla(medias_g, row.names = FALSE, digits = 1, col.names = c("Árbol", "Exposición", "Media del árbol (cm²)"))
Árbol Exposición Media del árbol (cm²)
G2_T1 sol 83,9
G1_T1 semi 12,6
G1_T2 semi 13,9
G3_T1 sombra 26,8
G3_T2 sombra 27,6
por_expo <- do.call(rbind, lapply(split(medias_g, droplevels(medias_g$exposicion)), function(d)
  data.frame(exposicion = as.character(d$exposicion[1]), arboles = nrow(d), hojas = 10 * nrow(d),
             media = mean(d$area_cm2), de = if (nrow(d) > 1) sd(d$area_cm2) else NA_real_,
             minimo = min(d$area_cm2), maximo = max(d$area_cm2))))
tabla(por_expo, row.names = FALSE, digits = c(0, 0, 0, 1, 1, 1, 1),
      col.names = c("Exposición", "Árboles", "Hojas", "Media de los árboles", "DE entre árboles", "Mín.", "Máx."),
      caption = "Árboles realmente independientes por categoría de exposición (unidad = el árbol).")
Árboles realmente independientes por categoría de exposición (unidad = el árbol).
Exposición Árboles Hojas Media de los árboles DE entre árboles Mín. Máx.
sol 1 10 83,9 83,9 83,9
semi 2 20 13,3 0,9 12,6 13,9
sombra 2 20 27,2 0,6 26,8 27,6
# Orden y colores definidos aquí, para que no dependan de otros chunks
niveles_expo <- c("sol", "semi", "sombra")
col_expo     <- c(sol = "#E69F00", semi = "#009E73", sombra = "#0072B2")
oscurecer <- function(col, f = 0.6) {
  m <- col2rgb(col) / 255 * f
  rgb(m[1, ], m[2, ], m[3, ])
}

# Un valor por árbol: su media
mg <- aggregate(area_cm2 ~ id_arbol + exposicion, data = datos, FUN = mean)
mg$exposicion <- factor(mg$exposicion, levels = niveles_expo)
mg <- mg[order(mg$exposicion, mg$id_arbol), ]

arboles  <- resumen$arbol
simbolos <- c(16, 17, 15, 18, 8)[seq_along(arboles)]
x        <- as.integer(mg$exposicion)
desfase  <- ave(x, x, FUN = function(v) if (length(v) == 1) 0 else seq(-0.12, 0.12, length.out = length(v)))
n_arb    <- table(mg$exposicion)
media_g  <- tapply(mg$area_cm2, mg$exposicion, mean)     # media de los árboles por exposición

par(mar = c(5, 4.8, 3, 1))
plot(NULL, xlim = c(0.5, 3.5), ylim = range(datos$area_cm2), xaxt = "n", las = 1,
     xlab = "Exposición", ylab = expression("Área foliar (cm"^2*")"),
     main = "Media por Árboles y Exposición")
axis(1, at = 1:3, tick = FALSE, line = 0.5,
     labels = paste0(niveles_expo, "\n(", n_arb, ifelse(n_arb == 1, " árbol)", " árboles)")))

# Hojas al fondo, tenues
set.seed(2)
hx <- as.integer(factor(datos$exposicion, levels = niveles_expo))
points(hx + runif(nrow(datos), -0.22, 0.22), datos$area_cm2,
       pch = 16, cex = 0.6, col = adjustcolor("grey40", 0.35))

# Línea: media de los árboles de cada exposición
segments(1:3 - 0.3, media_g, 1:3 + 0.3, media_g, lwd = 3, col = oscurecer(col_expo[niveles_expo]))

# Un punto grande por árbol
points(x + desfase, mg$area_cm2, cex = 2, lwd = 2,
       pch = simbolos[match(mg$id_arbol, arboles)],
       col = oscurecer(col_expo[as.character(mg$exposicion)], 0.8))

legend("topright", legend = c(arboles, "hoja"), pch = c(simbolos, 16),
       pt.cex = c(rep(1.3, length(arboles)), 0.6), bty = "n", title = "Árbol", cex = 0.85)

Esto deja 5 datos independientes en lugar de 50. 2 árboles de sombra, 2 de semisombra y 1 de sol. Debido a que hay un único árbol de sol no es posible calcular la variación dentro de esa categoría (la DE queda sin calcular), y la comparación sol–sombra de la guía no puede hacerse como prueba estadística.

5.5.1 ¿Qué tan raro sería ver esa diferencia por azar?

Dado el tamaño muestral tan reducido, es preferible recurrir a una prueba de permutación exacta en lugar de asumir una distribución teórica. Si la exposición no tuviera un efecto real, cualquier redistribución de las etiquetas sol y sombra entre los árboles sería igualmente probable. De este modo, se calcula la diferencia para todas las combinaciones posibles y se determina la posición exacta que ocupa el valor observado dentro de esa distribución nula.

col_expo <- c(sol = "#E69F00", semi = "#009E73", sombra = "#0072B2")

# Semisombra se agrupa con sombra (solo para esta prueba)
medias_g$exposicion2 <- ifelse(medias_g$exposicion == "semi", "sombra",
                               as.character(medias_g$exposicion))
stopifnot(!anyNA(medias_g$exposicion2))

n_sol    <- sum(medias_g$exposicion2 == "sol")
n_sombra <- sum(medias_g$exposicion2 == "sombra")

y        <- medias_g$area_cm2
es_ss    <- medias_g$exposicion2 == "sombra"
n_ss     <- sum(es_ss)

repartos <- combn(length(y), n_ss)                 # todas las formas de elegir los árboles de "sombra"
dif_perm <- apply(repartos, 2, function(i) mean(y[i]) - mean(y[-i]))
dif_obs  <- mean(y[es_ss]) - mean(y[!es_ss])
p_perm   <- mean(abs(dif_perm) >= abs(dif_obs) - 1e-9)
p_min    <- 1 / ncol(repartos)

par(mar = c(4.5, 4.8, 3, 1))
plot(dif_perm, rep(0, length(dif_perm)), pch = 21, bg = "#D8F3DC", col = "#2D6A4F", cex = 2.2,
     yaxt = "n", ylim = c(-1, 1),
     ylab = "", xlab = expression("Diferencia sombra - sol (cm"^2*")"),
     main = paste(ncol(repartos), "repartos posibles"))
points(dif_obs, 0, pch = 21, bg = col_expo["sombra"], col = "white", lwd = 2, cex = 2.6)
abline(v = 0, lty = 3, col = "#5B6B62")
legend("topright", legend = "reparto observado", pch = 21, pt.bg = col_expo["sombra"], bty = "n", pt.cex = 1.6)

Hay 5 repartos posibles; la diferencia observada (sombra − sol ≈ −63,7 cm²) es la 1.ª más extrema, así que p = 0,200. El valor más pequeño que cualquier resultado podría dar con 4 y 1 árboles sería 0,200. Con 5 árboles, y solo uno en sol, el diseño no puede dar resultados “significativos” al 5 %, sean cuales sean los datos. Los árboles de semisombra se agruparon con los de sombra por ser ambos condiciones sin sol pleno.

5.5.2 Lo que habría pasado ignorando el árbol

fmt_p <- function(p) ifelse(p < 0.001, "< 0,001",
                            formatC(p, format = "f", digits = 3, decimal.mark = ","))

dg <- datos
dg$sin_sol <- dg$exposicion != "sol"
t_hojas <- t.test(area_cm2 ~ sin_sol, data = dg)              # trata las hojas como independientes
p_hojas <- t_hojas$p.value
dif_hojas <- unname(t_hojas$estimate[2] - t_hojas$estimate[1])

comparacion_g <- data.frame(
  Análisis = c("Hojas como datos independientes (incorrecto)", "Un promedio por árbol (permutación exacta)"),
  n_sol = c(sum(!dg$sin_sol), sum(!es_ss)), n_sin_sol = c(sum(dg$sin_sol), n_ss),
  Diferencia = c(fmt(dif_hojas), fmt(dif_obs)), p = c(fmt_p(p_hojas), fmt_p(p_perm)))
tabla(comparacion_g, col.names = c("Análisis", "n sol", "n sin sol pleno", "Diferencia (cm²)", "p"),
      align = "lrrrr")
Análisis n sol n sin sol pleno Diferencia (cm²) p
Hojas como datos independientes (incorrecto) 10 40 -63,7 < 0,001
Un promedio por árbol (permutación exacta) 1 4 -63,7 0,200

Tratar las hojas como independientes multiplica por 10 el tamaño de la muestra (50 hojas en lugar de 5 árboles) y cambia el p de 0,200 a menos de 0,001, aunque la diferencia es exactamente la misma (−63,7 cm²). Esa precisión es falsa: se llama pseudorreplicación. Las hojas de un árbol son 10 mediciones de lo mismo, no 10 árboles. En particular, las 10 hojas en sol vienen de un único árbol (G2_T1), así que no aportan 10 réplicas sino una.

5.5.3 ¿Depende el resultado de un solo árbol?

Al tener una cantidad limitada de árboles, la ausencia de uno solo impactaría significativamente en los datos.

medias_g$sin_sol <- medias_g$exposicion != "sol"       # semi y sombra = "sin sol pleno"

loo <- do.call(rbind, lapply(seq_len(nrow(medias_g)), function(i) {
  d <- medias_g[-i, ]
  dif <- if (any(!d$sin_sol) && any(d$sin_sol))
    mean(d$area_cm2[d$sin_sol]) - mean(d$area_cm2[!d$sin_sol]) else NA_real_
  data.frame(sin_el_arbol = medias_g$id_arbol[i],
             exposicion = as.character(medias_g$exposicion[i]),
             n_sol = sum(!d$sin_sol), n_sin_sol = sum(d$sin_sol),
             dif = ifelse(is.na(dif), "no se puede calcular", fmt(dif, 1)))
}))
tabla(loo, row.names = FALSE,
      col.names = c("Árbol que se quita", "Su exposición", "Árboles de sol",
                    "Árboles sin sol pleno", "Diferencia (sin sol pleno - sol), cm²"),
      align = "llrrr",
      caption = "Sensibilidad de la diferencia al quitar un árbol.")
Sensibilidad de la diferencia al quitar un árbol.
Árbol que se quita Su exposición Árboles de sol Árboles sin sol pleno Diferencia (sin sol pleno - sol), cm²
G2_T1 sol 0 4 no se puede calcular
G1_T1 semi 1 3 -61,2
G1_T2 semi 1 3 -61,6
G3_T1 sombra 1 3 -65,9
G3_T2 sombra 1 3 -66,1

Quitando uno por uno los árboles de semisombra y sombra, la diferencia se mantiene estable, entre −61,2 y −66,1 cm² (frente a −63,7 cm² con los cinco). Pero si se quita G2_T1, no queda ningún árbol de sol y la comparación deja de existir. Todo el resultado se apoya en ese único árbol.

6 Diseño experimental, ANOVA y comparaciones post-ANOVA

Hasta este punto, la comparación entre las condiciones de exposición (sol y sombra) se abordó mediante promedios por árbol empleando pruebas \(t\), de Wilcoxon y de permutación. El Análisis de Varianza (ANOVA) permite generalizar esta comparación aprovechando la estructura jerárquica completa del diseño experimental. En esta sección se abordan tres preguntas clave, cada una evaluada mediante la herramienta estadística correspondiente:

Preguntas y herramientas.
Pregunta Herramienta Después del ANOVA
¿Difieren entre sí los árboles del grupo? ANOVA de un factor (árbol) Tukey HSD: ¿cuáles árboles?
¿Hay efecto de la exposición respetando que las hojas están dentro de árboles? ANOVA anidado (árbol dentro de exposición) Componentes de varianza

6.1 Diseño Experimental

El estudio corresponde a un diseño observacional con una estructura jerárquica o anidada. Los componentes del diseño y su función analítica se definen a continuación:

  • Factor de interés (efecto fijo): Exposición solar, evaluada en tres niveles (sol, semisombra y sombra).

  • Factor de bloqueo (efecto aleatorio/bloque): El grupo de trabajo. Dado que cada grupo evaluó árboles bajo ambas condiciones de luz, la comparación sol-sombra se realiza intra-bloque. Esto permite aislar la variabilidad introducida por la selección de distintas especies o sitios de muestreo, evitando que se confunda con el efecto de la exposición.

  • Unidad experimental: El árbol, dado que la condición de exposición solar es una propiedad atribuible al individuo en su totalidad.

  • Unidad de muestreo (seudorrÉplicas / submuestras): La hoja. Las 10 hojas recolectadas por individuo constituyen mediciones repetidas para estimar el valor del árbol y no representan réplicas independientes de la condición de exposición.

Con esos elementos, el modelo es:

log(área) ~ grupo + exposición + grupo:exposición + árbol(grupo × exposición) + error de hoja

El término árbol(grupo × exposición) (árboles dentro de cada combinación) es el error experimental contra el que se prueba la exposición. Si ese término se ignora y se usa el error de las hojas, se cae en la pseudorreplicación que vimos antes.

El diseño no está balanceado: cada grupo tiene 2 árboles de semisombra, 2 árboles de sombra y 1 árbol de sol.

Justificación de la transformación logarítmica (\(\log\)): La transformación logarítmica del área foliar se justifica por dos razones teóricas y estadísticas fundamentales:

  • Homocedasticidad y escala: Las medidas de superficie son estrictamente positivas y presentan una variabilidad proporcional a la magnitud de la hoja (las hojas de mayor tamaño exhiben una mayor dispersión o desviación estándar que las pequeñas). Al aplicar \(\log(\text{Área})\), se estabiliza la varianza entre los individuos evaluados, aproximando los datos a los supuestos de normalidad y homocedasticidad.

  • Interpretación multiplicativa: Bajo la escala logarítmica, las diferencias entre promedios se interpretan en términos de proporciones o razones relativas (por ejemplo, un incremento de \(1.3 \times\) o un cambio porcentual), lo cual resulta biológicamente más congruente al comparar la alometría y el tamaño foliar.

La presencia de esta heterocedasticidad en la escala original y su corrección mediante la transformación pueden verificarse empíricamente evaluando la relación lineal entre la media (\(\bar{x}\)) y la desviación estándar (\(s\)) de cada árbol.

media_orig <- tapply(datos$area_cm2,      datos$id_arbol, mean)
de_orig    <- tapply(datos$area_cm2,      datos$id_arbol, sd)
media_log  <- tapply(log(datos$area_cm2), datos$id_arbol, mean)
de_log     <- tapply(log(datos$area_cm2), datos$id_arbol, sd)

r_orig <- cor(media_orig, de_orig)
r_log  <- cor(media_log,  de_log)

tabla(data.frame(Escala = c("Original (cm²)", "Logaritmo"),
                 Correlación = fmt(c(r_orig, r_log), 2)),
      align = "lr",
      caption = "Correlación entre la media y la desviación estándar de cada árbol.")
Correlación entre la media y la desviación estándar de cada árbol.
Escala Correlación
Original (cm²) 0,99
Logaritmo 0,05

Entre árboles, la desviación estándar crece con la media en la escala original (correlación 0,99), y esa relación desaparece con el logaritmo (0,05). Esto cumple mejor el supuesto de varianzas parecidas que exige el ANOVA.

6.2 ANOVA de un Grupo: ¿Difieren los Árboles del Grupo?

Se compara el logaritmo del área de las hojas entre los 5 árboles del grupo. Aquí las hojas sí son réplicas (de cada árbol), y la pregunta es por esos árboles concretos, no por la exposición.

dg <- datos
dg$id_arbol <- factor(dg$id_arbol)
m1 <- lm(log(area_cm2) ~ id_arbol, data = dg)
a1 <- tabla_anova(m1)
a1$Fuente <- c("Entre árboles", "Dentro de árboles (hojas)")
tabla(formato_anova(a1), row.names = FALSE, align = "lrrrrr",
      caption = "ANOVA de un factor sobre log(área), hojas del grupo.")
ANOVA de un factor sobre log(área), hojas del grupo.
Fuente gl SC CM F p
Entre árboles 4 22,781 5,695 47,08 < 0,001
Dentro de árboles (hojas) 45 5,443 0,121

El ANOVA de un factor sobre log(área) muestra diferencias claras entre los árboles (F(4, 45) = 47,08; p < 0,001): cerca del 81 % de la variación se debe a diferencias entre árboles y solo el 19 % a la variación entre hojas de un mismo árbol. Esto indica que las hojas de un árbol se parecen más entre sí que a las de otro, lo que refuerza que el árbol, y no la hoja, es la unidad de análisis. El ANOVA no indica qué árboles difieren ni a qué se debe la diferencia; para lo primero se aplica la prueba de Tukey.

Los supuestos indican que los residuos deberían ser aproximadamente normales y tener varianza parecida entre árboles.

if (!exists("fmt_p")) fmt_p <- function(p) ifelse(p < 0.001, "< 0,001",
                                                  formatC(p, format = "f", digits = 3, decimal.mark = ","))

m1 <- lm(log(area_cm2) ~ id_arbol, data = datos)   # el ANOVA de un factor (bórrala si ya tienes m1 definido arriba)

par(mfrow = c(1, 2), mar = c(4.5, 4.8, 3, 1))
plot(fitted(m1), resid(m1), pch = 16, col = adjustcolor("black", 0.5), las = 1,
     xlab = "Valor ajustado (log área)", ylab = "Residuo", main = "Residuos vs ajustados")
abline(h = 0, lty = 2)
qqnorm(resid(m1), pch = 16, col = adjustcolor("black", 0.5), las = 1, main = "Normalidad de los residuos",
       xlab = "Cuantiles teóricos", ylab = "Cuantiles de los residuos")
qqline(resid(m1))

par(mfrow = c(1, 1))

shap1 <- shapiro.test(resid(m1))
flig1 <- fligner.test(log(area_cm2) ~ id_arbol, data = datos)
kw1   <- kruskal.test(log(area_cm2) ~ id_arbol, data = datos)   # alternativa sin supuesto de normalidad

supuestos <- data.frame(
  Prueba = c("Shapiro-Wilk", "Fligner-Killeen", "Kruskal-Wallis"),
  `Qué evalúa` = c("Normalidad de los residuos",
                   "Varianzas parecidas entre árboles",
                   "Diferencias entre árboles, sin suponer normalidad"),
  Estadístico = fmt(c(shap1$statistic, flig1$statistic, kw1$statistic), 3),
  p = fmt_p(c(shap1$p.value, flig1$p.value, kw1$p.value)),
  Lectura = c(ifelse(shap1$p.value >= 0.05, "Se cumple", "No se cumple"),
              ifelse(flig1$p.value >= 0.05, "Se cumple", "No se cumple"),
              ifelse(kw1$p.value  <  0.05, "Hay diferencias", "Sin diferencias")),
  check.names = FALSE)

tabla(supuestos, align = "lllrrl",
      caption = "Pruebas de supuestos del ANOVA de un factor sobre log(área).")
Pruebas de supuestos del ANOVA de un factor sobre log(área).
Prueba Qué evalúa Estadístico p Lectura
W Shapiro-Wilk Normalidad de los residuos 0,972 0,277 Se cumple
Fligner-Killeen:med chi-squared Fligner-Killeen Varianzas parecidas entre árboles 2,106 0,716 Se cumple
Kruskal-Wallis chi-squared Kruskal-Wallis Diferencias entre árboles, sin suponer normalidad 37,277 < 0,001 Hay diferencias

Los residuos del ANOVA no se apartan de la normalidad (Shapiro-Wilk, p ≈ 0,28) y las varianzas de log(área) son parecidas entre árboles (Fligner-Killeen, p ≈ 0,7), por lo que se cumplen los supuestos. Como comprobación, la prueba de Kruskal-Wallis, que no supone normalidad, también detecta diferencias entre árboles (p < 0,001).

6.3 Post-ANOVA: ¿qué árboles difieren? (Tukey HSD)

Con 5 árboles hay 10 comparaciones por pares. Si se hicieran 10 pruebas t sueltas al 5 %, la probabilidad de al menos un falso positivo sería de alrededor de 40 %. La prueba de Tukey HSD compara todos los pares y controla ese error para el conjunto completo.

tk <- TukeyHSD(aov(log(area_cm2) ~ id_arbol, data = dg))$id_arbol
tk_tab <- data.frame(comparacion = gsub("-", " / ", rownames(tk)),
                     razon = exp(tk[, "diff"]), li = exp(tk[, "lwr"]), ls = exp(tk[, "upr"]),
                     p_aj = tk[, "p adj"], stringsAsFactors = FALSE)
tk_tab <- tk_tab[order(tk_tab$p_aj), ]

# ¿Cuántos pares que difieren son de árboles con la MISMA exposición?
pares_ids <- strsplit(tk_tab$comparacion, " / ")
misma_expo <- sapply(pares_ids, function(x) length(unique(resumen$exposicion[match(x, resumen$arbol)])) == 1)
n_misma_sig <- sum(misma_expo & tk_tab$p_aj < 0.05)

tabla_tk <- data.frame(tk_tab$comparacion, fmt(tk_tab$razon, 2),
                       paste0("[", fmt(tk_tab$li, 2), "; ", fmt(tk_tab$ls, 2), "]"),
                       fmt_p(tk_tab$p_aj), ifelse(tk_tab$p_aj < 0.05, "sí", "no"))
tabla(tabla_tk, col.names = c("Comparación (A / B)", "Razón A / B", "IC 95 % (Tukey)", "p ajustado", "Difieren (5 %)"),
      align = "lrrrr", caption = "Comparaciones de Tukey entre árboles del grupo (escala logarítmica, mostradas como razones).")
Comparaciones de Tukey entre árboles del grupo (escala logarítmica, mostradas como razones).
Comparación (A / B) Razón A / B IC 95 % (Tukey) p ajustado Difieren (5 %)
G2_T1 / G1_T1 6,58 [4,23; 10,23] < 0,001 sí
G2_T1 / G1_T2 6,02 [3,87; 9,36] < 0,001 sí
G3_T1 / G2_T1 0,33 [0,21; 0,52] < 0,001 sí
G3_T2 / G2_T1 0,34 [0,22; 0,52] < 0,001 sí
G3_T2 / G1_T1 2,20 [1,42; 3,43] < 0,001 sí
G3_T1 / G1_T1 2,18 [1,40; 3,39] < 0,001 sí
G3_T2 / G1_T2 2,02 [1,30; 3,14] < 0,001 sí
G3_T1 / G1_T2 1,99 [1,28; 3,10] < 0,001 sí
G1_T2 / G1_T1 1,09 [0,70; 1,70] 0,979 no
G3_T2 / G3_T1 1,01 [0,65; 1,57] 1,000 no
k <- nrow(tk_tab)
par(mar = c(4.5, 9, 3, 1))
plot(tk_tab$razon, seq_len(k), log = "x", pch = 16, yaxt = "n", ylab = "",
     xlim = range(c(tk_tab$li, tk_tab$ls)), cex = 1.2,
     col = ifelse(tk_tab$p_aj < 0.05, "#D55E00", "grey40"),
     xlab = "Razón entre árboles (escala logarítmica)", main = "Comparaciones por pares")
segments(tk_tab$li, seq_len(k), tk_tab$ls, seq_len(k), lwd = 2,
         col = ifelse(tk_tab$p_aj < 0.05, "#D55E00", "grey40"))
axis(2, at = seq_len(k), labels = tk_tab$comparacion, las = 1, cex.axis = 0.8)
abline(v = 1, lty = 2)

La prueba de Tukey sobre log(área) separa los árboles en tres grupos que coinciden con la exposición. Los dos árboles de semisombra no difieren entre sí (razón 1,09; p = 0,979), ni los dos de sombra (razón 1,01; p = 1,000), mientras que todas las comparaciones entre exposiciones distintas son significativas (p < 0,001). El árbol de sol (G2_T1) tiene hojas unas 6 veces mayores que las de semisombra y unas 3 veces mayores que las de sombra, y los árboles de sombra, unas 2 veces mayores que los de semisombra. Esta prueba compara árboles y no demuestra el efecto de la exposición: con un solo árbol en sol, esa diferencia podría deberse también a otras características de ese árbol.

6.4 ANOVA anidado: el efecto de la exposición con el error correcto

Ahora con los árboles de todos los grupos. Las hojas están dentro de árboles y los árboles dentro de una exposición: un diseño anidado. El efecto de la exposición se prueba contra la variación entre árboles, no contra la variación entre hojas.

lim <- datos
lim$expo  <- factor(ifelse(lim$exposicion == "semi", "sombra", as.character(lim$exposicion)),
                    levels = c("sol", "sombra"))
lim$arbol <- factor(lim$id_arbol)

m_anid <- lm(log(area_cm2) ~ expo + arbol, data = lim)   # el árbol está dentro de expo (cada árbol tiene una sola exposición)
a_an   <- tabla_anova(m_anid)

# Cada fuente se prueba contra el cuadrado medio que corresponde a su unidad
F_expo  <- a_an$CM[1] / a_an$CM[2]; p_expo  <- pf(F_expo,  a_an$gl[1], a_an$gl[2], lower.tail = FALSE)
F_arbol <- a_an$CM[2] / a_an$CM[3]; p_arbol <- pf(F_arbol, a_an$gl[2], a_an$gl[3], lower.tail = FALSE)

tab_an <- data.frame(
  Fuente = c("Exposición", "Árbol (dentro de exposición)", "Hojas (residual)"),
  gl = a_an$gl, SC = fmt(a_an$SC, 3), CM = fmt(a_an$CM, 3),
  Contra = c("CM de árbol", "CM de hojas", ""),
  F = c(fmt(F_expo, 2), fmt(F_arbol, 2), ""),
  p = c(fmt_p(p_expo), fmt_p(p_arbol), ""))
tabla(tab_an, row.names = FALSE, align = "lrrrlrr",
      caption = "ANOVA anidado sobre log(área): hojas dentro de árboles dentro de exposición.")
ANOVA anidado sobre log(área): hojas dentro de árboles dentro de exposición.
Fuente gl SC CM Contra F p
Exposición 1 17,264 17,264 CM de árbol 9,39 0,055
Árbol (dentro de exposición) 3 5,517 1,839 CM de hojas 15,20 < 0,001
Hojas (residual) 45 5,443 0,121
  • Exposición: F(1; 3) = 9,39, p = 0,055: con el árbol como unidad, la diferencia entre sol y sombra queda en el límite y no alcanza el 5 %.

  • Árbol (dentro de exposición): p < 0,001. Árboles de la misma exposición difieren entre sí; ese es el ruido contra el que debe competir el efecto de la exposición.

  • La versión ingenua (probar la exposición contra el CM de las hojas) daría p < 0,001, una certeza que los datos no respaldan.

Cuánto de la variación se debe al árbol y cuánto a las hojas (componentes de varianza, de forma aproximada por el desbalance):

n0      <- nrow(lim) / nlevels(lim$arbol)                     # hojas por árbol (aquí son 10 en todos)
s2_res  <- a_an$CM[3]
s2_arb  <- max((a_an$CM[2] - a_an$CM[3]) / n0, 0)
pct_arb <- 100 * s2_arb / (s2_arb + s2_res)

tabla(data.frame(Componente = c("Entre árboles (dentro de exposición)", "Entre hojas (mismo árbol)"),
                 Varianza = fmt(c(s2_arb, s2_res), 4),
                 `% de la variación` = fmt(c(pct_arb, 100 - pct_arb), 1),
                 check.names = FALSE),
      align = "lrr",
      caption = "Componentes de varianza sobre log(área), después de quitar la exposición.")
Componentes de varianza sobre log(área), después de quitar la exposición.
Componente Varianza % de la variación
Entre árboles (dentro de exposición) 0,1718 58,7
Entre hojas (mismo árbol) 0,1210 41,3

Alrededor del 59 % de la variación (en log) que queda después de quitar la exposición se debe a diferencias entre árboles y el resto (41 %) a diferencias entre hojas de un mismo árbol. Por eso conviene medir más árboles antes que más hojas por árbol.

7 Discusión de Resultados.

Sobre qué se encontró, con el árbol como unidad de análisis, el árbol de sol tuvo hojas de mayor área media (83,9 cm², 1 árbol) que los de sombra (27,2 cm², 2 árboles) y que los de semisombra (13,3 cm², 2 árboles). Es el sentido contrario a la hipótesis, que esperaba hojas más grandes a la sombra. Pero este resultado no se puede considerar del todo verídico:

  1. La diferencia entre sol y sin sol pleno (−63,7 cm²) tiene un p exacto de 0,200, y con 5 árboles (1 contra 4) el menor valor posible es 0,2: el diseño no permite obtener evidencia estadística de una diferencia.

  2. Depende de un solo árbol: sin G2_T1 no queda ningún árbol de sol y la comparación desaparece. Si se quita cualquiera de los otros cuatro, la diferencia se mantiene entre −61,2 y −66,1 cm².

  3. El ANOVA anidado, que prueba la exposición contra la variación entre árboles, da p = 0,055: queda en el límite, sin alcanzar el 5 %.

Si la pregunta es si esto coincide con la hipótesis planteada inicialmente, no: los datos no respaldan que las hojas de sombra sean más grandes, pero tampoco la refutan. Con un solo árbol de sol, el diseño no tiene capacidad para detectar ni para descartar esa diferencia. Lo que sí se ve con claridad es que los árboles difieren entre sí (ANOVA, F(4; 45) = 47,08; p < 0,001) y que, según Tukey, forman tres grupos que coinciden con la exposición: los dos árboles de semisombra no difieren entre sí, ni los dos de sombra. El orden observado (sol > sombra > semisombra) no sigue un gradiente de luz, porque la semisombra, que debería ser intermedia, tuvo las hojas más pequeñas.

Posibles explicaciones ambientales (son hipótesis para explicar el patrón, no algo que estos datos demuestren):

  • Luz. A la sombra, una lámina mayor intercepta más luz; a pleno sol las hojas, más pequeñas y gruesas, ya tienen luz de sobra. Este patrón clásico no aparece en nuestros datos, y no se puede saber si es porque no existe en estas especies o porque el diseño no alcanza a verlo.

  • Temperatura. Una hoja pequeña tiene una capa de aire más delgada en su borde y se enfría con más facilidad, lo que es una ventaja a pleno sol. Una hoja grande a pleno sol necesitaría compensarlo con otros mecanismos, como una mayor transpiración.

  • Agua. A pleno sol la demanda de evaporación es mayor y las hojas pequeñas pierden menos agua; pero si el agua no es limitante, un árbol de sol puede sostener hojas grandes. El muestreo fue el 22 de octubre, un mes que suele ser lluvioso en Cali, y no se midió la humedad del suelo.

  • Suelo pavimentado. Los árboles están junto a la calle, rodeados en parte por vías, andenes o concreto, lo que puede limitar el espacio de las raíces y el agua que llega a ellas. No se registró cuánto suelo pavimentado rodea a cada árbol, así que no se puede evaluar su efecto.

Qué más pudo influir (explicaciones alternativas que hay que descartar antes de atribuirlo todo a la luz):

  • El árbol, y no solo su exposición. Los componentes de varianza indican que cerca del 59 % de la variación (en log) que queda después de quitar la exposición se debe a diferencias entre árboles. Si G2_T1 pertenece a una especie o morfotipo de hoja grande, la diferencia sería de composición de especies y no de respuesta a la luz.

  • Edad y tamaño del árbol, y la calidad del suelo donde crece.

  • Cómo se eligieron las hojas. Las hojas escogidas en varios árboles fueron las más accesibles a la hora de colectar, pues varios árboles tenían una altura bastante considerable.

  • La clasificación en sol, semisombra y sombra. La categoría de semisombra no tiene una definición escrita en la guía, y se agrupó con la sombra para la prueba de permutación y el ANOVA anidado. Esa agrupación no es neutral: los árboles de semisombra y sombra difieren entre sí (unas 2 veces según Tukey), lo que aumenta la variación entre árboles y vuelve más conservadora la prueba de la exposición.

  • Error de medición. El área depende del trazo, de la foto y de los lados del marco que se escriben en el script. Tres hojas de G1_T1 (hojas 1, 9 y 10) quedaron fuera de los límites de Tukey de su árbol; no se encontró causa de medición y se conservaron, y quitarlas cambia poco la media del árbol (12,6 a 11,6 cm²).

Resultados frente a la hipótesis.

Es un resultado (lo que los datos muestran) Es una hipótesis (lo que habría que probar)
En estos 5 árboles del campus, el de sol tuvo la mayor área foliar media, pero es un solo árbol (G2_T1). Que las hojas de sombra son más grandes que las de sol en los árboles del campus (o lo contrario).
Los árboles difieren entre sí en el tamaño de sus hojas, y los dos de cada exposición se parecen entre sí. Que las diferencias entre árboles se deben a la exposición y no a la especie, a la edad o al suelo.
El diseño tiene 1 árbol de sol, 2 de semisombra y 2 de sombra: no permite probar la hipótesis. Que la respuesta a la luz es igual en todas las especies y en cualquier época del año.

Para poder tener la capacidad de responder la pregunta, se deberían haber muestreado más árboles por categoría (al menos 2 de sol y, mejor, muchos más: la base conjunta de todos los grupos sería el paso natural); registrar la especie o morfotipo y medir la luz en lugar de estimarla.

8 Limitaciones.

  • Pocos árboles. Son 5 árboles en total, con 1 de sol, 2 de semisombra y 2 de sombra. Con una sola réplica de sol no se puede estimar la variación entre árboles dentro de esa categoría, y la comparación sol–sombra descansa en un árbol contra cuatro (con la semisombra agrupada con la sombra). [Si la guía pide al menos 2 árboles por categoría, agrega: “La guía pide al menos 2 árboles por categoría y no se cumplió en sol”.]

  • Un solo grupo. Las estimaciones de un grupo con 5 árboles son muy inestables: quitar G2_T1, el único árbol de sol, elimina la comparación por completo. Quitar cualquiera de los otros cuatro cambia poco la diferencia (de −61,2 a −66,1 cm², frente a −63,7).

  • No hubo asignación al azar. Los árboles ya estaban en el sol, la semisombra o la sombra: es un estudio observacional. Se puede hablar de asociación, no de que la luz cause hojas más grandes o más pequeñas.

  • La exposición es una categoría gruesa, decidida a ojo. No se midió la luz ni se registró la especie. Además, para la prueba de permutación y el ANOVA anidado se agrupó con la sombra, lo que no es neutral: Tukey muestra que los árboles de semisombra y sombra difieren entre sí (unas 2 veces) y eso aumenta la variación entre árboles.

  • Hojas elegidas por personas. Debido a limitaciones fisicas en la colección, no se puede afirmar que las hojas se eligieron al azar, pues las hojas altas son difíciles de alcanzar.

  • Un solo momento. Las hojas se midieron el 22/10/2026; el área puede cambiar con la época del año y con el estado hídrico del árbol: se sabe que durante el mes de octubre se estuvo en época de lluvias.

  • Supuestos de las pruebas. Con 10 hojas por árbol y 5 árboles, los supuestos del ANOVA se comprueban con poca potencia. Los residuos y las varianzas no mostraron problemas (Shapiro-Wilk y Fligner-Killeen no rechazaron), y la conclusión se verificó con Kruskal-Wallis, que no supone normalidad.

  • Potencia del ANOVA anidado. El error para probar la exposición tiene solo 3 grados de libertad, así que un resultado no significativo (p = 0,055) no es evidencia de que no haya efecto.

  • Comparaciones múltiples. Las 10 comparaciones entre árboles se ajustaron con Tukey; aun así, son exploratorias.

9 Información de la Sesión.

Entorno de trabajo.
Elemento Detalle
R R version 4.5.0 (2025-04-11 ucrt)
Sistema operativo Windows 11 x64 (build 26200)
Fecha del informe 08/11/2026
Paquetes utilizados.
Paquete Versión Uso
readxl 1.4.5 Lectura del archivo Excel
knitr 1.52 Tablas y generación del informe
rmarkdown 2.30 Generación del informe
leaflet 2.2.3 Mapa interactivo de los árboles
htmltools 0.5.9 Galería de fotos y ventanas emergentes