Universidad Nacional de Jujuy

Facultad de Ciencias Agrarias

Cátedra de Bioestadística y Diseño Experimental

Profesora: Ing. Agr. Ivone Carolina Humacata

Clase práctica: Diseño Cuadrado Latino (DCL)


1. Propósito de la clase

Se continuará con el ejemplo de vitamina C en jugo de naranja, pero se utilizará un cuadrado latino de orden 5 para comparar cinco métodos de conservación y controlar simultáneamente dos fuentes de variabilidad: filas y columnas.

En un cuadrado latino de orden 5 existen:

  • 5 tratamientos;
  • 5 filas;
  • 5 columnas;
  • 25 unidades experimentales;
  • 5 repeticiones por tratamiento.

Cada tratamiento aparece exactamente una vez en cada fila y una vez en cada columna.12


2. Situación experimental

Se desea evaluar el efecto de cinco métodos de conservación sobre el contenido de vitamina C en jugo de naranja después de siete días.

Tratamientos

Código Método de conservación Descripción
T1 Ambiente 25 °C
T2 Refrigeración 4 °C
T3 Congelación −18 °C
T4 Envase opaco 4 °C, protegido de la luz
T5 Atmósfera reducida 4 °C, con mínimo contacto con oxígeno

La variable respuesta será:

\[ Y=\text{contenido de vitamina C en mg/100 mL} \]


3. Definición del diseño

Orden del cuadrado

El número de tratamientos determina el orden:

\[ p=5 \]

Tamaño total

\[ N=p^2=5^2=25 \]

Por lo tanto:

  • 25 unidades experimentales;
  • 5 unidades por fila;
  • 5 unidades por columna;
  • 5 unidades por tratamiento.

Unidad experimental

Cada envase individual de jugo de naranja de 200 mL.

Unidad de observación

El valor de vitamina C medido en cada envase.

Factor de interés

Método de conservación, con cinco niveles.

Factores de bloqueo

Para este ejemplo:

  • Filas: cinco días o corridas analíticas.
  • Columnas: cinco posiciones de análisis o secuencias dentro de cada corrida.

La elección de filas y columnas debe estar justificada. No se deben utilizar dos factores de bloqueo solamente porque el diseño lo exige.


4. Modelo matemático

El modelo del cuadrado latino es:

\[ Y_{ijk}=\mu+\tau_i+\rho_j+\kappa_k+\varepsilon_{ijk} \]

donde:

En R:

VitaminaC_mg100mL ~ Fila + Columna + Tratamiento

Hipótesis para tratamientos

\[ H_0:\tau_1=\tau_2=\tau_3=\tau_4=\tau_5=0 \]

No existen diferencias entre los métodos de conservación.

\[ H_1: \]

Al menos un tratamiento presenta una media diferente.


5. Grados de libertad

Para un cuadrado latino de orden \(p=5\):

Fuente de variación Grados de libertad
Filas \(p-1=4\)
Columnas \(p-1=4\)
Tratamientos \(p-1=4\)
Error \((p-1)(p-2)=12\)
Total \(p^2-1=24\)

6. Aleatorización

La aleatorización se realiza en tres etapas:

  1. Construir un cuadrado latino básico.
  2. Permutar aleatoriamente las filas.
  3. Permutar aleatoriamente las columnas.
  4. Asignar aleatoriamente los nombres de los tratamientos a las letras o códigos del cuadrado.

No se deben sortear las 25 celdas de manera independiente, porque se perdería la propiedad de que cada tratamiento aparece una sola vez por fila y columna. La permutación de filas, columnas y etiquetas conserva la estructura del cuadrado.34


6.1. Cuadrado latino básico

T1 T2 T3 T4 T5
T2 T3 T4 T5 T1
T3 T4 T5 T1 T2
T4 T5 T1 T2 T3
T5 T1 T2 T3 T4

Cada tratamiento aparece una vez en cada fila y columna.


6.2. Script para aleatorizar el cuadrado

# ============================================================
# ALEATORIZACIÓN DE UN CUADRADO LATINO DE ORDEN 5
# Ejemplo: vitamina C en jugo de naranja
# ============================================================

library(dplyr)
library(tidyr)
library(writexl)

set.seed(20260901)

# Tratamientos
tratamientos <- c(
  "T1_25C",
  "T2_4C",
  "T3_menos18C",
  "T4_opaco",
  "T5_atmosfera_reducida"
)

# Filas y columnas
filas <- paste0("F", 1:5)
columnas <- paste0("C", 1:5)

# ------------------------------------------------------------
# 1. Crear cuadrado latino básico
# ------------------------------------------------------------

cuadrado_base <- matrix(
  c(
    "A", "B", "C", "D", "E",
    "B", "C", "D", "E", "A",
    "C", "D", "E", "A", "B",
    "D", "E", "A", "B", "C",
    "E", "A", "B", "C", "D"
  ),
  nrow = 5,
  byrow = TRUE,
  dimnames = list(filas, columnas)
)

print("Cuadrado latino básico:")
print(cuadrado_base)

# ------------------------------------------------------------
# 2. Aleatorizar filas y columnas
# ------------------------------------------------------------

orden_filas <- sample(filas)
orden_columnas <- sample(columnas)

cuadrado_permutado <- cuadrado_base[
  orden_filas,
  orden_columnas,
  drop = FALSE
]

# ------------------------------------------------------------
# 3. Aleatorizar las etiquetas de tratamientos
# ------------------------------------------------------------

letras <- c("A", "B", "C", "D", "E")
tratamientos_aleatorizados <- sample(tratamientos)

correspondencia <- data.frame(
  Letra = letras,
  Tratamiento = tratamientos_aleatorizados
)

# Reemplazar letras por tratamientos
for (i in seq_along(letras)) {
  cuadrado_permutado[
    cuadrado_permutado == letras[i]
  ] <- tratamientos_aleatorizados[i]
}

print("Orden aleatorio de filas:")
print(orden_filas)

print("Orden aleatorio de columnas:")
print(orden_columnas)

print("Correspondencia de letras y tratamientos:")
print(correspondencia)

print("Cuadrado latino aleatorizado:")
print(cuadrado_permutado)

7. Convertir el cuadrado en una base de datos

# Convertir la matriz a formato largo
plan <- as.data.frame(as.table(cuadrado_permutado))

names(plan) <- c(
  "Fila",
  "Columna",
  "Tratamiento"
)

# Crear identificadores de unidades experimentales
plan <- plan %>%
  mutate(
    UE = paste0("UE", sprintf("%02d", 1:n())),
    Fila = factor(Fila, levels = filas),
    Columna = factor(Columna, levels = columnas),
    Tratamiento = factor(
      Tratamiento,
      levels = tratamientos
    ),
    Temp_Conservacion_C = case_when(
      Tratamiento == "T1_25C" ~ 25,
      Tratamiento == "T2_4C" ~ 4,
      Tratamiento == "T3_menos18C" ~ -18,
      Tratamiento == "T4_opaco" ~ 4,
      Tratamiento == "T5_atmosfera_reducida" ~ 4
    )
  ) %>%
  select(
    UE,
    Fila,
    Columna,
    Tratamiento,
    Temp_Conservacion_C
  )

print(plan)

8. Verificación del cuadrado latino

8.1. Cinco tratamientos por fila

with(plan, table(Fila, Tratamiento))

Cada fila debe contener una vez cada tratamiento:

    T1 T2 T3 T4 T5
F1   1  1  1  1  1
F2   1  1  1  1  1
F3   1  1  1  1  1
F4   1  1  1  1  1
F5   1  1  1  1  1

8.2. Cinco tratamientos por columna

with(plan, table(Columna, Tratamiento))

También debe contener únicamente unos:

    T1 T2 T3 T4 T5
C1   1  1  1  1  1
C2   1  1  1  1  1
C3   1  1  1  1  1
C4   1  1  1  1  1
C5   1  1  1  1  1

8.3. Cinco repeticiones por tratamiento

table(plan$Tratamiento)

Resultado esperado:

T1_25C              5
T2_4C               5
T3_menos18C         5
T4_opaco            5
T5_atmosfera_reducida 5

9. Preparación de la planilla de campo

Se agregan las variables que se completarán durante el ensayo:

plan <- plan %>%
  mutate(
    Vol_DCPIP_mL = NA_real_,
    VitaminaC_mg100mL = NA_real_,
    Fecha_Analisis = NA_character_,
    Analista = NA_character_,
    Observaciones = NA_character_
  )

La planilla tendrá una estructura como esta:

UE Fila Columna Tratamiento Temperatura Vol. DCPIP Vitamina C
UE01 F1 C1 T3_menos18C −18
UE02 F1 C2 T5_atmosfera_reducida 4
UE03 F1 C3 T1_25C 25

Una fila representa una unidad experimental y una columna representa una variable.


10. Exportar la planificación

# Tabla de asignación de tratamientos
asignacion <- plan %>%
  select(
    Fila,
    Columna,
    UE,
    Tratamiento,
    Temp_Conservacion_C
  )

# Resumen del diseño
resumen <- data.frame(
  Parametro = c(
    "Diseño",
    "Orden del cuadrado",
    "Número de tratamientos",
    "Número de filas",
    "Número de columnas",
    "Total de unidades experimentales",
    "Repeticiones por tratamiento"
  ),
  Valor = c(
    "Cuadrado latino",
    5,
    5,
    5,
    5,
    25,
    5
  )
)

# Exportar
write_xlsx(
  list(
    Plan_Cuadrado_Latino = plan,
    Asignacion = asignacion,
    Resumen_Diseno = resumen,
    Correspondencia = correspondencia
  ),
  "plan_cuadrado_latino_orden5.xlsx"
)

11. Datos experimentales

Una vez realizado el ensayo, se completan:

Los datos simulados se encuentran en archivo llamado:

datos_vitamina_c_DCL.xlsx

12. Importación desde Excel a R

# ============================================================
# IMPORTACIÓN DE DATOS
# ============================================================

library(readxl)
library(janitor)
library(dplyr)

datos <- read_excel(
  "datos_vitamina_c_DCL.xlsx",
  sheet = "Datos_Raw"
) %>%
  clean_names()

names(datos)
str(datos)
summary(datos)

Conversión de variables:

datos <- datos %>%
  mutate(
    ue = factor(ue),
    fila = factor(fila),
    columna = factor(columna),
    tratamiento = factor(
      tratamiento,
      levels = c(
        "T1_25C",
        "T2_4C",
        "T3_menos18C",
        "T4_opaco",
        "T5_atmosfera_reducida"
      )
    ),
    vitamina_c = as.numeric(vitamina_c_mg100m_l)
  )

Si el nombre de la columna cambia al usar clean_names(), verificarlo mediante:

names(datos)

13. Estadística descriptiva

# ============================================================
# ESTADÍSTICA DESCRIPTIVA
# ============================================================

descriptivos <- datos %>%
  group_by(tratamiento) %>%
  summarise(
    n = n(),
    media = mean(vitamina_c),
    mediana = median(vitamina_c),
    desviacion_estandar = sd(vitamina_c),
    varianza = var(vitamina_c),
    error_estandar =
      desviacion_estandar / sqrt(n),
    minimo = min(vitamina_c),
    maximo = max(vitamina_c),
    cv =
      desviacion_estandar / media * 100
  )

print(descriptivos)

Resumen por filas:

datos %>%
  group_by(fila) %>%
  summarise(
    n = n(),
    media = mean(vitamina_c),
    desviacion_estandar = sd(vitamina_c)
  )

Resumen por columnas:

datos %>%
  group_by(columna) %>%
  summarise(
    n = n(),
    media = mean(vitamina_c),
    desviacion_estandar = sd(vitamina_c)
  )

14. Gráficos

14.1. Boxplot de tratamientos

library(ggplot2)

ggplot(
  datos,
  aes(
    x = tratamiento,
    y = vitamina_c,
    fill = tratamiento
  )
) +
  geom_boxplot(alpha = 0.65) +
  geom_jitter(
    width = 0.10,
    size = 2.5,
    color = "black"
  ) +
  labs(
    title = "Contenido de vitamina C por tratamiento",
    x = "Método de conservación",
    y = "Vitamina C (mg/100 mL)"
  ) +
  theme_minimal() +
  theme(
    legend.position = "none",
    axis.text.x = element_text(
      angle = 25,
      hjust = 1
    )
  )

14.2. Mapa del cuadrado latino

ggplot(
  datos,
  aes(
    x = columna,
    y = fila,
    fill = tratamiento
  )
) +
  geom_tile(
    color = "white",
    linewidth = 1
  ) +
  geom_text(
    aes(label = round(vitamina_c, 1)),
    color = "black",
    size = 4
  ) +
  labs(
    title = "Cuadrado latino de orden 5",
    subtitle = "Valores observados de vitamina C",
    x = "Columna",
    y = "Fila",
    fill = "Tratamiento"
  ) +
  theme_minimal()

14.3. Medias por tratamiento

ggplot(
  descriptivos,
  aes(
    x = tratamiento,
    y = media,
    fill = tratamiento
  )
) +
  geom_col(alpha = 0.7) +
  geom_errorbar(
    aes(
      ymin = media - error_estandar,
      ymax = media + error_estandar
    ),
    width = 0.2
  ) +
  labs(
    title = "Medias de vitamina C por tratamiento",
    x = "Tratamiento",
    y = "Media de vitamina C (mg/100 mL)"
  ) +
  theme_minimal() +
  theme(
    legend.position = "none",
    axis.text.x = element_text(
      angle = 25,
      hjust = 1
    )
  )

15. Modelo y ANOVA

# ============================================================
# MODELO CUADRADO LATINO DE ORDEN 5
# ============================================================

modelo_cl5 <- aov(
  vitamina_c ~ fila + columna + tratamiento,
  data = datos
)

summary(modelo_cl5)
anova(modelo_cl5)

La fórmula incluye los tres efectos:

vitamina_c ~ fila + columna + tratamiento

No debe incluirse una interacción:

vitamina_c ~ fila * columna * tratamiento

porque el cuadrado latino clásico tiene una sola observación por celda y no permite estimar adecuadamente esas interacciones.


16. Verificación de supuestos

16.1. Normalidad

# ============================================================
# NORMALIDAD DE LOS RESIDUOS
# ============================================================

residuos <- residuals(modelo_cl5)

shapiro.test(residuos)

qqnorm(
  residuos,
  main = "Q-Q plot de residuos"
)

qqline(
  residuos,
  col = "red",
  lwd = 2
)

Con 12 grados de libertad residuales, esta evaluación será más informativa que en el cuadrado de orden 3. Sin embargo, el p-valor debe interpretarse junto con el gráfico y el conocimiento del proceso.

16.2. Homogeneidad de varianzas

library(car)

leveneTest(
  vitamina_c ~ tratamiento,
  data = datos
)

También se puede utilizar un gráfico de residuos:

plot(
  modelo_cl5,
  which = 1,
  main = "Residuos versus valores ajustados"
)

16.3. Gráficos diagnósticos

par(mfrow = c(2, 2))
plot(modelo_cl5)
par(mfrow = c(1, 1))

Se deben buscar:

  • ausencia de patrones en los residuos;
  • dispersión aproximadamente constante;
  • puntos extremos;
  • alineación razonable en el gráfico Q-Q.

17. Comparación de medias con Tukey

# ============================================================
# TUKEY PARA TRATAMIENTOS
# ============================================================

tukey_cl5 <- TukeyHSD(
  modelo_cl5,
  which = "tratamiento",
  conf.level = 0.95
)

print(tukey_cl5)

plot(
  tukey_cl5,
  las = 1,
  col = "steelblue"
)

La prueba compara los diez pares posibles entre cinco tratamientos:

\[ \binom{5}{2}=10 \]

Es decir:


17.1. Medias ajustadas

library(emmeans)

medias_ajustadas <- emmeans(
  modelo_cl5,
  ~ tratamiento
)

print(medias_ajustadas)

Comparaciones:

comparaciones_tukey <- pairs(
  medias_ajustadas,
  adjust = "tukey"
)

print(comparaciones_tukey)
confint(comparaciones_tukey)

Agrupamiento con letras:

library(multcomp)
library(multcompView)

grupos_tukey <- cld(
  medias_ajustadas,
  adjust = "tukey",
  Letters = letters
)

print(grupos_tukey)

Los tratamientos que comparten una letra no presentan diferencias significativas según Tukey.

La conclusión debe responder:

¿Existen diferencias en el contenido de vitamina C entre los cinco métodos de conservación después de controlar simultáneamente la variabilidad asociada a las filas y las columnas?


18. Script completo resumido

# ============================================================
# ANÁLISIS COMPLETO
# CUADRADO LATINO DE ORDEN 5
# ============================================================

library(readxl)
library(openxlsx)
library(tidyverse)
library(janitor)
library(car)
library(emmeans)
library(multcomp)
library(multcompView)

# 1. Importar
datos <- read_excel(
  "datos_vitamina_c_DCL.xlsx",
  sheet = "Datos_Raw"
) %>%
  clean_names()

str(datos)

# 2. Preparar
datos <- datos %>%
  mutate(
    ue = factor(ue),
    fila = factor(fila),
    columna = factor(columna),
    tratamiento = factor(
      tratamiento,
      levels = c(
        "T1_25C",
        "T2_4C",
        "T3_menos18C",
        "T4_opaco",
        "T5_atmosfera_reducida"
      )
    ),
    vitamina_c = as.numeric(vitamina_c_mg100m_l)
  )

# 3. Verificar estructura
str(datos)
summary(datos)

with(datos, table(fila, tratamiento))
with(datos, table(columna, tratamiento))
table(datos$tratamiento)

# 4. Descriptivos
descriptivos <- datos %>%
  group_by(tratamiento) %>%
  summarise(
    n = n(),
    media = mean(vitamina_c),
    mediana = median(vitamina_c),
    desviacion_estandar = sd(vitamina_c),
    error_estandar = sd(vitamina_c) / sqrt(n()),
    minimo = min(vitamina_c),
    maximo = max(vitamina_c),
    cv = sd(vitamina_c) / mean(vitamina_c) * 100
  )

print(descriptivos)

 gráficos

ggplot(
  datos,
  aes(
    x = tratamiento,
    y = vitamina_c,
    fill = tratamiento
  )
) +
  geom_boxplot(alpha = 0.65) +
  geom_jitter(
    width = 0.10,
    size = 2.5,
    color = "black"
  ) +
  labs(
    title = "Contenido de vitamina C por tratamiento",
    x = "Método de conservación",
    y = "Vitamina C (mg/100 mL)"
  ) +
  theme_minimal() +
  theme(
    legend.position = "none",
    axis.text.x = element_text(
      angle = 25,
      hjust = 1
    )
  )
  
# 5. Modelo
modelo_cl5 <- aov(
  vitamina_c ~ fila + columna + tratamiento,
  data = datos
)

# 6. ANOVA
summary(modelo_cl5)
anova(modelo_cl5)

# 7. Supuestos
residuos <- residuals(modelo_cl5)

shapiro.test(residuos)

qqnorm(residuos)
qqline(residuos, col = "red", lwd = 2)

leveneTest(
  vitamina_c ~ tratamiento,
  data = datos
)

par(mfrow = c(2, 2))
plot(modelo_cl5)
par(mfrow = c(1, 1))

# 8. Tukey
tukey_cl5 <- TukeyHSD(
  modelo_cl5,
  which = "tratamiento"
)

print(tukey_cl5)
plot(tukey_cl5)

# 9. Medias ajustadas
medias <- emmeans(
  modelo_cl5,
  ~ tratamiento
)

print(medias)

comparaciones <- pairs(
  medias,
  adjust = "tukey"
)

print(comparaciones)
confint(comparaciones)

# 10. Letras
grupos <- cld(
  medias,
  adjust = "tukey",
  Letters = letters
)

print(grupos)

# 11. Exportar

# Descriptivos 
write.xlsx(
  descriptivos,
  file = "descriptivos_cuadrado_latino_orden5.xlsx",
  sheetName = "Descriptivos",
  rowNames = FALSE
)

# ANOVA 
write.xlsx(
  as.data.frame(anova(modelo_cl5)),
  file = "anova_cuadrado_latino_orden5.xlsx",
  sheetName = "ANOVA",
  rowNames = TRUE
)

# Comparaciones 
write.xlsx(
  as.data.frame(comparaciones),
  file = "tukey_cuadrado_latino_orden5.xlsx",
  sheetName = "Tukey",
  rowNames = FALSE
)

# Grupos Tukey 
write.xlsx(
  as.data.frame(grupos),
  file = "grupos_tukey_cuadrado_latino_orden5.xlsx",
  sheetName = "Grupos",
  rowNames = FALSE
)

Consideración metodológica final

El cuadrado latino de orden 5 permite controlar dos fuentes de variación con solo 25 unidades, pero exige que:

  • las filas sean relativamente homogéneas;
  • las columnas sean relativamente homogéneas;
  • cada combinación fila–columna tenga una sola unidad;
  • no existan interacciones importantes entre tratamientos y bloques;
  • los tratamientos sean comparables y aplicables bajo el mismo protocolo.

Nota de uso: Este material ha sido elaborado por Ivone Carolina Humacata para fines académicos en la Facultad de Ciencias Agrarias – UNJu, con apoyo de herramientas de inteligencia artificial (Perplexity, Microsoft Copilot). En caso de utilizarlo, por favor cite de la siguiente manera: Humacata, I. C. (2026). Clase práctica: Diseño Cuadrado Latino (DCL). Universidad Nacional de Jujuy. Material docente elaborado con apoyo de inteligencia artificial.

56789101112131415



  1. https://spanish.arabpsychology.com/trm/cuadrado-latino-equilibrado-balanced-latin-square/↩︎

  2. https://es.slideshare.net/slideshow/diseno-de-bloque-un-4-1-pptvvcccvvccccbhmmm/283732585↩︎

  3. https://www.scribd.com/presentation/864513158/07-Latin-Square-Design-LSD-1↩︎

  4. https://www.scribd.com/document/969550307/The-square-design-latino-2016-pdf↩︎

  5. https://www.rdocumentation.org/packages/aridagri/versions/2.0.3/topics/anova_latin↩︎

  6. https://r-statistics.co/Latin-Square-Design-in-R.html↩︎

  7. https://gpai.app/s/cheatsheet/xIhTFlbf/latin-square-design↩︎

  8. https://r-statistics.co/Experimental-Design-Exercises-in-R.html↩︎

  9. https://www.scribd.com/document/914036709/Latin-square-design↩︎

  10. https://www.studocu.com/pe/document/institucion-educativa-jorge-basadre/matematica/diseno-cuadrado-latino/144727926?origin=related-document↩︎

  11. https://socialsci.libretexts.org/Courses/Taft_College/Research_Methods_for_the_Social_and_Behavioral_Sciences/08:\_\_Experimental_Research/8.04:\_Repeated_Measures_Design↩︎

  12. https://thestippe.github.io/statistics/latin_square↩︎

  13. https://www.scribd.com/presentation/930454086/unit-6↩︎

  14. https://www.scribd.com/doc/186658707/Output↩︎

  15. https://es.scribd.com/document/892662818/Diseno-contrabalanceado-o-diseno-de-cuadrado-latino↩︎