Al finalizar la clase, los estudiantes serán capaces de:
emmeans y Tukey.Un experimento factorial estudia simultáneamente dos o más factores y todas sus combinaciones posibles.
En el ejemplo de vitamina C se estudiarán dos factores:
| Nivel | Descripción |
|---|---|
| A1 | Temperatura ambiente, 25 °C |
| A2 | Refrigeración, 4 °C |
| A3 | Congelación, −18 °C |
| Nivel | Tiempo |
|---|---|
| B1 | 0 días |
| B2 | 7 días |
El arreglo factorial será:
\[ 3 \times 2 \]
Esto genera:
\[ 3 \times 2 = 6 \]
combinaciones de tratamientos.
| Código | Conservación | Tiempo | Combinación |
|---|---|---|---|
| A1B1 | Ambiente | 0 días | Ambiente × 0 |
| A1B2 | Ambiente | 7 días | Ambiente × 7 |
| A2B1 | Refrigeración | 0 días | Refrigeración × 0 |
| A2B2 | Refrigeración | 7 días | Refrigeración × 7 |
| A3B1 | Congelación | 0 días | Congelación × 0 |
| A3B2 | Congelación | 7 días | Congelación × 7 |
La variable respuesta será:
\[ Y=\text{contenido de vitamina C en mg/100 mL} \]
El diseño factorial permite responder tres preguntas:
La tercera pregunta corresponde a la interacción.
Compara las medias de vitamina C de los tres métodos de conservación, promediando los tiempos.
\[ H_0: \mu_{A1}=\mu_{A2}=\mu_{A3} \]
Compara la media de vitamina C a los 0 y 7 días, promediando los métodos.
\[ H_0: \mu_{B1}=\mu_{B2} \]
La interacción indica si el método de conservación depende del efecto del tiempo.
\[ H_0: \mu_{A1B1}=\mu_{A1B2}=\mu_{A2B1} ... \]
Por ejemplo:
La interacción debe analizarse antes de interpretar los efectos principales. Si es significativa, las medias de las combinaciones deben interpretarse con especial atención.
En un diseño completamente aleatorizado, se supone que las unidades experimentales son homogéneas y todos los tratamientos combinados se asignan aleatoriamente a todas las unidades.
\[ Y_{ijk}=\mu+\alpha_i+\beta_j+(\alpha\beta)_{ij}+\varepsilon_{ijk} \]
donde:
En RStudio:
vitamina_c ~ conservacion * tiempo
El símbolo * incluye:
conservacion + tiempo + conservacion:tiempo
En el DBCA se agrega un factor de bloqueo para controlar una fuente conocida de variación, por ejemplo:
Cada bloque debe contener todas las combinaciones factoriales. Esta es la misma lógica del DBCA: los bloques se forman por una fuente de variabilidad conocida y la aleatorización se realiza dentro de cada bloque.
\[ Y_{ijkl}= \mu+\alpha_i+\beta_j+(\alpha\beta)_{ij} +\rho_l+\varepsilon_{ijkl} \]
donde:
En R:
vitamina_c ~ bloque + conservacion * tiempo
Si se utilizan:
entonces:
\[ N=6 \times 5=30 \]
unidades experimentales.
Si se utilizan:
entonces:
\[ N=6 \times 5=30 \]
unidades experimentales.
La diferencia no está en el número total, sino en la estructura:
# ============================================================
# DISEÑO FACTORIAL 3 x 2 EN DCA
# Vitamina C en jugo de naranja
# ============================================================
library(dplyr)
library(tidyr)
library(writexl)
set.seed(20260921)
# Niveles de los factores
conservacion <- c(
"Ambiente",
"Refrigeracion",
"Congelacion"
)
tiempo <- c(
"Dia_0",
"Dia_7"
)
repeticiones <- 5
# Crear todas las combinaciones factoriales
tratamientos_dca <- expand.grid(
Conservacion = conservacion,
Tiempo = tiempo,
Repeticion = 1:repeticiones
)
# Identificador de unidad experimental
tratamientos_dca <- tratamientos_dca %>%
mutate(
UE = paste0("UE", sprintf("%02d", 1:n())
)
)
# Aleatorizar todas las unidades del DCA
tratamientos_dca <- tratamientos_dca %>%
slice_sample(prop = 1) %>%
mutate(
Orden_Ejecucion = row_number()
)
# Revisar el diseño
print(tratamientos_dca)
# Comprobar cantidad por combinación
with(
tratamientos_dca,
table(Conservacion, Tiempo)
)
En el DCA, las 30 unidades se consideran homogéneas y la asignación se realiza sobre el conjunto completo.
Importar el archivo Excel “datos_factorial_DCA_vitamina_c.xlsx”
library(readxl)
library(janitor)
datos_dca <- read_excel(
"datos_factorial_DCA_vitamina_c.xlsx",
sheet = "Datos_Raw"
) %>%
clean_names()
Luego:
datos_dca <- datos_dca %>%
mutate(
ue = factor(ue),
conservacion = factor(conservacion),
tiempo = factor(tiempo),
vitamina_c = as.numeric(vitamina_c_mg100m_l)
)
# ============================================================
# ESTADÍSTICA DESCRIPTIVA
# ============================================================
desc_dca <- datos_dca %>%
group_by(conservacion, tiempo) %>%
summarise(
n = n(),
media = mean(vitamina_c),
mediana = median(vitamina_c),
sd = sd(vitamina_c),
se = sd / sqrt(n),
minimo = min(vitamina_c),
maximo = max(vitamina_c),
.groups = "drop"
)
print(desc_dca)
library(ggplot2)
ggplot(
desc_dca,
aes(
x = tiempo,
y = media,
group = conservacion,
color = conservacion
)
) +
geom_line(linewidth = 1) +
geom_point(size = 3) +
geom_errorbar(
aes(
ymin = media - se,
ymax = media + se
),
width = 0.1
) +
labs(
title = "Interacción entre conservación y tiempo",
x = "Tiempo de almacenamiento",
y = "Vitamina C media (mg/100 mL)",
color = "Conservación"
) +
theme_minimal()
El gráfico es exploratorio: la decisión formal se toma con el ANOVA.
# ============================================================
# MODELO FACTORIAL EN DCA
# ============================================================
modelo_dca <- aov(
vitamina_c ~ conservacion * tiempo,
data = datos_dca
)
summary(modelo_dca)
anova(modelo_dca)
La tabla ANOVA contiene:
Si la interacción es significativa, no conviene interpretar solamente las medias generales de conservación o tiempo. Se deben comparar las seis combinaciones.
library(emmeans)
medias_dca <- emmeans(
modelo_dca,
~ conservacion * tiempo
)
print(medias_dca)
comparaciones_dca <- pairs(
medias_dca,
adjust = "tukey"
)
print(comparaciones_dca)
confint(comparaciones_dca)
library(multcomp)
library(multcompView)
grupos_dca <- cld(
medias_dca,
adjust = "tukey",
Letters = letters
)
print(grupos_dca)
Las combinaciones que comparten una letra no presentan diferencias significativas.
Si la interacción es significativa, puede preguntarse:
metodos_por_tiempo <- emmeans(
modelo_dca,
~ conservacion | tiempo
)
pairs(
metodos_por_tiempo,
adjust = "tukey"
)
tiempos_por_metodo <- emmeans(
modelo_dca,
~ tiempo | conservacion
)
pairs(
tiempos_por_metodo,
adjust = "tukey"
)
Estas comparaciones son más informativas que comparar solamente los efectos principales.
# ============================================================
# SUPUESTOS DEL MODELO DCA
# ============================================================
residuos_dca <- residuals(modelo_dca)
# Normalidad
shapiro.test(residuos_dca)
qqnorm(residuos_dca)
qqline(residuos_dca, col = "red", lwd = 2)
# Homogeneidad de varianzas
library(car)
leveneTest(
vitamina_c ~ conservacion * tiempo,
data = datos_dca
)
# Diagnósticos generales
par(mfrow = c(2, 2))
plot(modelo_dca)
par(mfrow = c(1, 1))
Para el DBCA se utilizarán:
Cada bloque debe contener:
Ambiente × Día 0
Ambiente × Día 7
Refrigeración × Día 0
Refrigeración × Día 7
Congelación × Día 0
Congelación × Día 7
Por ejemplo, el bloque puede representar una corrida analítica o un lote de jugo. Los tratamientos factoriales se aleatorizan dentro de cada bloque. Este procedimiento mantiene la comparación de todas las combinaciones bajo una condición de bloque.
# ============================================================
# DISEÑO FACTORIAL 3 x 2 EN DBCA
# ============================================================
set.seed(20260921)
numero_bloques <- 5
# Crear las seis combinaciones factoriales
combinaciones <- expand.grid(
Conservacion = conservacion,
Tiempo = tiempo
)
# Repetir todas las combinaciones en cada bloque
datos_dbca <- expand.grid(
Bloque = paste0("B", 1:numero_bloques),
Conservacion = conservacion,
Tiempo = tiempo
) %>%
group_by(Bloque) %>%
mutate(
Orden_Bloque = sample(row_number())
) %>%
arrange(Bloque, Orden_Bloque) %>%
ungroup() %>%
mutate(
UE = paste0("UE", sprintf("%02d", 1:n())),
Bloque = factor(Bloque),
Conservacion = factor(Conservacion),
Tiempo = factor(Tiempo)
)
print(datos_dbca)
# Comprobar que cada bloque contiene las 6 combinaciones
with(
datos_dbca,
table(Bloque, Conservacion, Tiempo)
)
La tabla debe mostrar una observación por combinación dentro de cada bloque.
datos_dbca <- read_excel(
"datos_factorial_DBCA_vitamina_c.xlsx",
sheet = "Datos_Raw"
) %>%
clean_names()
str(datos_dbca)
Luego
datos_dbca <- datos_dbca %>%
mutate(
ue = factor(ue),
bloque = factor(bloque),
conservacion = factor(conservacion),
tiempo = factor(tiempo),
vitamina_c = as.numeric(vitamina_c_mg100m_l)
)
str(datos_dbca)
# ============================================================
# MODELO FACTORIAL EN DBCA
# ============================================================
modelo_dbca <- aov(
vitamina_c ~ bloque + conservacion * tiempo,
data = datos_dbca
)
summary(modelo_dbca)
anova(modelo_dbca)
El modelo incluye:
vitamina_c ~ bloque +
conservacion +
tiempo +
conservacion:tiempo
El bloque se incorpora para reducir el error experimental.
# ============================================================
# DESCRIPTIVOS DEL DBCA
# ============================================================
desc_dbca <- datos_dbca %>%
group_by(conservacion, tiempo) %>%
summarise(
n = n(),
media = mean(vitamina_c),
mediana = median(vitamina_c),
sd = sd(vitamina_c),
se = sd / sqrt(n()),
minimo = min(vitamina_c),
maximo = max(vitamina_c),
.groups = "drop"
)
print(desc_dbca)
Resumen por bloque:
datos_dbca %>%
group_by(bloque) %>%
summarise(
n = n(),
media = mean(vitamina_c),
sd = sd(vitamina_c)
)
ggplot(
desc_dbca,
aes(
x = tiempo,
y = media,
group = conservacion,
color = conservacion
)
) +
geom_line(linewidth = 1) +
geom_point(size = 3) +
geom_errorbar(
aes(
ymin = media - se,
ymax = media + se
),
width = 0.1
) +
labs(
title = "Interaccion en el DBCA factorial",
x = "Tiempo",
y = "Vitamina C media (mg/100 mL)",
color = "Conservación"
) +
theme_minimal()
# ============================================================
# ANOVA DEL DBCA FACTORIAL
# ============================================================
anova_dbca <- anova(modelo_dbca)
print(anova_dbca)
La tabla separará:
Interpretar la interacción.
medias_dbca <- emmeans(
modelo_dbca,
~ conservacion * tiempo
)
print(medias_dbca)
tukey_dbca <- pairs(
medias_dbca,
adjust = "tukey"
)
print(tukey_dbca)
confint(tukey_dbca)
grupos_dbca <- cld(
medias_dbca,
adjust = "tukey",
Letters = letters
)
print(grupos_dbca)
conservacion_por_tiempo <- emmeans(
modelo_dbca,
~ conservacion | tiempo
)
pairs(
conservacion_por_tiempo,
adjust = "tukey"
)
tiempo_por_conservacion <- emmeans(
modelo_dbca,
~ tiempo | conservacion
)
pairs(
tiempo_por_conservacion,
adjust = "tukey"
)
Si se considera Ambiente × Día 7 como control o
referencia, se pueden comparar las demás combinaciones contra esa
condición.
Primero se crea un factor combinado:
# ============================================================
# DUNNETT CON UNA COMBINACIÓN CONTROL
# ============================================================
datos_dbca <- datos_dbca %>%
mutate(
combinacion = interaction(
conservacion,
tiempo,
sep = "_"
)
)
modelo_combinacion <- aov(
vitamina_c ~ bloque + combinacion,
data = datos_dbca
)
medias_combinacion <- emmeans(
modelo_combinacion,
~ combinacion
)
print(medias_combinacion)
Para utilizar Dunnett, se puede definir como referencia:
# Ver niveles disponibles
levels(datos_dbca$combinacion)
Después:
comparaciones_dunnett <- contrast(
medias_combinacion,
method = "trt.vs.ctrl",
ref = "Ambiente_Dia_7",
adjust = "dunnett"
)
print(comparaciones_dunnett)
confint(comparaciones_dunnett)
La etiqueta exacta del control dependerá de cómo RStudio construya los niveles. Por eso siempre conviene consultar:
levels(datos_dbca$combinacion)
Dunnett compara cada condición contra un único control. No responde
si, por ejemplo, Refrigeracion_Dia_0 difiere de
Congelacion_Dia_0; para eso se utiliza Tukey.12
# ============================================================
# SUPUESTOS DEL DBCA FACTORIAL
# ============================================================
residuos_dbca <- residuals(modelo_dbca)
# Normalidad
shapiro.test(residuos_dbca)
qqnorm(
residuos_dbca,
main = "Q-Q plot de residuos del DBCA"
)
qqline(
residuos_dbca,
col = "red",
lwd = 2
)
# Homogeneidad de varianzas
leveneTest(
vitamina_c ~ conservacion * tiempo,
data = datos_dbca
)
# Diagnósticos
par(mfrow = c(2, 2))
plot(modelo_dbca)
par(mfrow = c(1, 1))
La independencia se fundamenta en:
Se puede comparar el cuadrado medio del error de ambos modelos:
# ============================================================
# COMPARAR PRECISIÓN DCA VS. DBCA
# ============================================================
mse_dca <- deviance(modelo_dca) /
df.residual(modelo_dca)
mse_dbca <- deviance(modelo_dbca) /
df.residual(modelo_dbca)
cat("MSE del DCA:", mse_dca, "\n")
cat("MSE del DBCA:", mse_dbca, "\n")
reduccion_error <- (
(mse_dca - mse_dbca) / mse_dca
) * 100
cat(
"Reducción porcentual del error:",
round(reduccion_error, 2),
"%\n"
)
Si el MSE del DBCA es menor, el bloqueo permitió explicar parte de la variabilidad no atribuida a los tratamientos.
No obstante, el DBCA no siempre será mejor. Es adecuado solamente si el bloque representa una fuente real de variación y las unidades dentro de cada bloque son relativamente homogéneas.
# ============================================================
# SCRIPT SIMPLE: FACTORIAL EN DCA
# ============================================================
library(tidyverse)
library(emmeans)
library(multcomp)
library(multcompView)
library(car)
# Importar datos
datos_dca <- read_excel(
"datos_factorial_DCA_vitamina_c.xlsx",
sheet = "Datos_Raw"
) %>%
clean_names()
# Factores
datos_dca$conservacion <- factor(datos_dca$conservacion)
datos_dca$tiempo <- factor(datos_dca$tiempo)
# Descriptivos
datos_dca %>%
group_by(conservacion, tiempo) %>%
summarise(
n = n(),
media = mean(vitamina_c),
sd = sd(vitamina_c),
.groups = "drop"
)
# Gráfico de interacción
with(
datos_dca,
interaction.plot(
tiempo,
conservacion,
vitamina_c,
xlab = "Tiempo",
ylab = "Vitamina C",
trace.label = "Conservación"
)
)
# Modelo
modelo_dca <- aov(
vitamina_c ~ conservacion * tiempo,
data = datos_dca
)
# ANOVA
summary(modelo_dca)
# Supuestos
shapiro.test(residuals(modelo_dca))
leveneTest(
vitamina_c ~ conservacion * tiempo,
data = datos_dca
)
# Medias ajustadas
medias_dca <- emmeans(
modelo_dca,
~ conservacion * tiempo
)
# Tukey
pairs(
medias_dca,
adjust = "tukey"
)
# Letras
cld(
medias_dca,
adjust = "tukey",
Letters = letters
)
# ============================================================
# SCRIPT SIMPLE: FACTORIAL EN DBCA
# ============================================================
library(tidyverse)
library(emmeans)
library(multcomp)
library(multcompView)
library(car)
# Importar datos
datos_dbca <- read_excel(
"datos_factorial_DBCA_vitamina_c.xlsx",
sheet = "Datos_Raw"
) %>%
clean_names()
# Convertir factores
datos_dbca$bloque <- factor(datos_dbca$bloque)
datos_dbca$conservacion <- factor(datos_dbca$conservacion)
datos_dbca$tiempo <- factor(datos_dbca$tiempo)
# Descriptivos
datos_dbca %>%
group_by(conservacion, tiempo) %>%
summarise(
n = n(),
media = mean(vitamina_c),
sd = sd(vitamina_c),
.groups = "drop"
)
# Modelo
modelo_dbca <- aov(
vitamina_c ~ bloque + conservacion * tiempo,
data = datos_dbca
)
# ANOVA
summary(modelo_dbca)
# Supuestos
shapiro.test(residuals(modelo_dbca))
leveneTest(
vitamina_c ~ conservacion * tiempo,
data = datos_dbca
)
# Medias ajustadas
medias_dbca <- emmeans(
modelo_dbca,
~ conservacion * tiempo
)
# Tukey
pairs(
medias_dbca,
adjust = "tukey"
)
# Letras
cld(
medias_dbca,
adjust = "tukey",
Letters = letters
)
# Efectos simples
pairs(
emmeans(modelo_dbca, ~ conservacion | tiempo),
adjust = "tukey"
)
pairs(
emmeans(modelo_dbca, ~ tiempo | conservacion),
adjust = "tukey"
)
La pregunta central será:
¿El efecto del método de conservación utilizado sobre la vitamina C depende del tiempo de almacenamiento?
Esta pregunta representa la principal ventaja de un experimento factorial: estudiar simultáneamente varios factores y determinar si actúan de manera independiente o conjunta.
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: Experimentos factoriales. Universidad Nacional de Jujuy. Material docente elaborado con apoyo de inteligencia artificial.
https://casrai.org/guides/dunnetts-test-comparisons-against-a-control↩︎
https://id.scribd.com/document/438817046/Arreglos-Factoriales-en-DBCA↩︎
https://cran.r-project.org/web/packages/PGaovR/refman/PGaovR.html↩︎
https://r-statistics.co/Experimental-Design-Exercises-in-R.html↩︎
https://cran.r-project.org/web/packages/aridagri/index.html↩︎
https://cran.r-project.org/web/packages/TukeyC/vignettes/TukeyC_intro.html↩︎