Se continuará con el ejemplo del contenido de vitamina C en jugo de naranja, pero se incorporará una fuente conocida de variabilidad: el día de análisis.
El objetivo es comparar tres métodos de conservación:
La variable respuesta será el contenido de vitamina C, expresado en mg/100 mL.
A diferencia del diseño completamente aleatorizado, en este caso las unidades experimentales se agrupan en bloques homogéneos. Dentro de cada bloque deben aparecer todos los tratamientos exactamente una vez. El modelo habitual es aditivo, sin incluir interacción tratamiento × bloque cuando existe una sola observación por combinación.12
Supongamos que el análisis de vitamina C no puede realizarse sobre las 24 muestras exactamente en las mismas condiciones. Puede haber diferencias entre días o corridas analíticas debido a:
Si esas diferencias se ignoran, pueden aumentar artificialmente el error experimental. Para controlarlas, se forman bloques internamente homogéneos. En cada bloque se incluyen los tres tratamientos y se aleatoriza su orden de análisis.
Se utilizarán:
Por lo tanto:
\[ N = t \times b = 3 \times 8 = 24 \]
donde:
Cada tratamiento tendrá 8 repeticiones, pero cada repetición estará asociada a un bloque diferente.
Todos los jugos de naranja pasteurizados de la marca y lote seleccionados.
24 envases de 200 mL, procedentes del mismo lote.
Cada envase individual de jugo.
La medición del contenido de vitamina C obtenida de cada envase.
Método de conservación, con tres niveles:
| Código | Tratamiento | Temperatura |
|---|---|---|
| T1 | Temperatura ambiente | 25 °C |
| T2 | Refrigeración | 4 °C |
| T3 | Congelación | −5 °C |
Día de análisis:
Cada bloque contiene:
\[ \{T1, T2, T3\} \]
Contenido de vitamina C en mg/100 mL.
El modelo para un diseño en bloques completos al azar es:
\[ Y_{ij}=\mu+\tau_i+\beta_j+\varepsilon_{ij} \]
donde:
Los índices son:
\[ i=25°C, 4°C, -5°C \]
para los tratamientos, y:
\[ j=1,2,\ldots,8 \]
para los bloques.
\[ H_0:\tau_1=\tau_2=\tau_3=0 \]
No existen diferencias entre los métodos de conservación.
\[ H_1: \]
Al menos un tratamiento presenta una media diferente.
\[ H_0:\beta_1=\beta_2=\cdots=\beta_8=0 \]
No existen diferencias entre bloques.
El efecto de los bloques no es el objetivo principal del ensayo. Su función es controlar una fuente de variabilidad conocida.
La aleatorización se realiza en dos niveles:
Cada bloque debe contener exactamente un envase de cada tratamiento. No se debe asignar, por ejemplo, T1 a todas las primeras unidades, T2 a todas las segundas y T3 a todas las terceras, porque eso podría confundir el efecto del tratamiento con el orden de análisis.
Dentro de cada bloque, los tres tratamientos se mezclan aleatoriamente. La semilla permite reproducir la asignación posteriormente. La aleatorización dentro de cada bloque es el procedimiento estándar del DBCA.34
Primero se generan 24 envases identificados como:
UE01, UE02, ..., UE24
Se asignan aleatoriamente tres unidades a cada bloque:
| Bloque | Unidades |
|---|---|
| B1 | UE03, UE02, UE023 |
| B2 | UE22, UE05, UE09 |
| B3 | UE17, UE04, UE12 |
| B4 | UE07, UE14, UE18 |
| B5 | UE10, UE11, UE15 |
| B6 | UE01, UE06, UE08 |
| B7 | UE16, UE20, UE21 |
| B8 | UE19, UE13, UE24 |
Posteriormente, dentro de cada bloque se sortean T1, T2 y T3.
# ============================================================
# ALEATORIZACIÓN DE UN DISEÑO EN BLOQUES COMPLETOS AL AZAR
# Ejemplo: vitamina C en jugo de naranja
# ============================================================
library(dplyr)
library(writexl)
set.seed(20260824)
# Parámetros
tratamientos <- c(
"T1_25C",
"T2_4C",
"T3_menos5C"
)
numero_bloques <- 8
tratamientos_por_bloque <- length(tratamientos)
total_unidades <- numero_bloques * tratamientos_por_bloque
# ------------------------------------------------------------
# 1. Crear las unidades como data.frame
# ------------------------------------------------------------
unidades <- data.frame(
UE = paste0("UE", sprintf("%02d", 1:total_unidades)),
stringsAsFactors = FALSE
)
# ------------------------------------------------------------
# 2. Aleatorizar las UE antes de formar los bloques
# ------------------------------------------------------------
unidades <- unidades[
sample(seq_len(nrow(unidades))),
,
drop = FALSE
]
# Crear bloques de tres unidades
unidades$Bloque <- rep(
paste0("B", 1:numero_bloques),
each = tratamientos_por_bloque
)
# Verificar
print(unidades)
# ------------------------------------------------------------
# 3. Aleatorizar tratamientos dentro de cada bloque
# ------------------------------------------------------------
plan <- unidades %>%
group_by(Bloque) %>%
mutate(
Tratamiento = sample(
tratamientos,
size = n(),
replace = FALSE
),
Orden_Analisis = sample(
seq_len(n()),
size = n(),
replace = FALSE
)
) %>%
ungroup()
# ------------------------------------------------------------
# 4. Agregar temperatura
# ------------------------------------------------------------
plan <- plan %>%
mutate(
Temp_Conservacion = case_when(
Tratamiento == "T1_25C" ~ 25,
Tratamiento == "T2_4C" ~ 4,
Tratamiento == "T3_menos5C" ~ -5
)
) %>%
arrange(Bloque, Orden_Analisis)
# Mostrar la planificación final
print(plan)
# ------------------------------------------------------------
# 5. Comprobaciones
# ------------------------------------------------------------
cat("\nCantidad de unidades por bloque:\n")
print(table(plan$Bloque))
cat("\nTratamientos dentro de cada bloque:\n")
print(with(plan, table(Bloque, Tratamiento)))
cat("\nCantidad total por tratamiento:\n")
print(table(plan$Tratamiento))
# ------------------------------------------------------------
# 6. Exportar
# ------------------------------------------------------------
write_xlsx(
list(
Plan_Completo = plan,
Unidades_Bloques = plan %>%
arrange(Bloque) %>%
select(Bloque, UE),
Tratamientos_Bloques = plan %>%
arrange(Bloque, Orden_Analisis) %>%
select(Bloque, Orden_Analisis, UE, Tratamiento)
),
"aleatorizacion_DBCA.xlsx"
)
La siguiente tabla debe mostrar una sola observación por combinación de bloque y tratamiento:
with(plan, table(Bloque, Tratamiento))
El resultado esperado es una tabla donde cada celda tenga valor 1:
T1_25C T2_4C T3_menos5C
B1 1 1 1
B2 1 1 1
B3 1 1 1
B4 1 1 1
B5 1 1 1
B6 1 1 1
B7 1 1 1
B8 1 1 1
Si algún bloque tiene dos unidades del mismo tratamiento o carece de otro tratamiento, la aleatorización es incorrecta y debe repetirse.
El archivo generado por R puede producir, por ejemplo, una asignación de este tipo:
| Bloque | Orden de análisis | UE | Tratamiento |
|---|---|---|---|
| B1 | 1 | UE02 | T3_menos5C |
| B1 | 2 | UE01 | T1_25C |
| B1 | 3 | UE03 | T2_4C |
| B2 | 1 | UE06 | T1_25C |
| B2 | 2 | UE04 | T2_4C |
| B2 | 3 | UE05 | T3_menos5C |
El orden exacto dependerá de la semilla y del algoritmo de aleatorización. Lo importante es que cada tratamiento aparezca una vez en cada bloque.
La planilla de campo puede organizarse de la siguiente manera:
| UE | Bloque | Orden | Tratamiento | Temperatura | Volumen DCPIP | Vitamina C |
|---|---|---|---|---|---|---|
| UE02 | B1 | 1 | T3_menos5C | −5 | 11.20 | 56.00 |
| UE01 | B1 | 2 | T1_25C | 25 | 8.60 | 43.00 |
| UE03 | B1 | 3 | T2_4C | 4 | 10.10 | 50.50 |
La estructura debe respetar el principio:
Una fila representa una unidad experimental y cada columna representa una variable.
Para el análisis en R, el archivo Excel se llama:
datos_vitamina_c_DBCA.xlsx
Y debe incluir, como mínimo, estas columnas:
UE
Bloque
Orden_Analisis
Tratamiento
Temp_Conservacion
Vol_DCPIP_mL
VitaminaC_mg100mL
Fecha_Analisis
Analista
Observaciones
# ============================================================
# ANÁLISIS ESTADÍSTICO DE UN DBCA
# Vitamina C en jugo de naranja
# ============================================================
# Instalar una sola vez, si fuera necesario
# install.packages(c(
# "readxl", "openxlsx", tidyverse", "janitor", "car",
# "emmeans", "agricolae", "writexl", "broom"
# ))
library(readxl)
library(tidyverse)
library(janitor)
library(car)
library(emmeans)
library(agricolae)
library(writexl)
library(broom)
library(openxlsx)
# Importar datos desde Excel
datos_raw <- read_excel(
"datos_vitamina_c_DBCA.xlsx",
sheet = "Datos_Raw"
)
# Limpiar nombres de columnas
datos <- datos_raw %>%
clean_names()
# Revisar nombres originales después de clean_names()
names(datos)
# Adaptar estos nombres si la planilla fue creada con nombres diferentes
datos <- datos %>%
rename(
ue = ue,
bloque = bloque,
orden_analisis = orden_analisis,
tratamiento = tratamiento,
temp_conservacion = temp_conservacion_c,
volumen_dcpip = vol_dcpip_m_l,
vitamina_c = vitamina_c_mg100m_l
)
# Convertir variables categóricas a factores
datos <- datos %>%
mutate(
ue = factor(ue),
bloque = factor(bloque),
tratamiento = factor(
tratamiento,
levels = c("T1_25C", "T2_4C", "T3_menos5C")
),
orden_analisis = as.numeric(orden_analisis),
vitamina_c = as.numeric(vitamina_c)
)
# Revisar estructura
str(datos)
summary(datos)
# Comprobar valores faltantes
colSums(is.na(datos))
# Comprobar cantidad de unidades
nrow(datos)
# Comprobar balance del DBCA
with(datos, table(bloque, tratamiento))
# ============================================================
# ESTADÍSTICA DESCRIPTIVA
# ============================================================
descriptivos_tratamiento <- 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),
coeficiente_variacion =
desviacion_estandar / media * 100,
minimo = min(vitamina_c),
maximo = max(vitamina_c),
cuartil_1 = quantile(vitamina_c, 0.25),
cuartil_3 = quantile(vitamina_c, 0.75)
)
print(descriptivos_tratamiento)
descriptivos_bloque <- datos %>%
group_by(bloque) %>%
summarise(
n = n(),
media = mean(vitamina_c),
desviacion_estandar = sd(vitamina_c)
)
print(descriptivos_bloque)
# Exportar descriptivos
write_xlsx(
list(
Descriptivos_Tratamiento = descriptivos_tratamiento,
Descriptivos_Bloque = descriptivos_bloque
),
"descriptivos_DBCA_vitamina_c.xlsx"
)
grafico_boxplot <- ggplot(
datos,
aes(x = tratamiento, y = vitamina_c, fill = tratamiento)
) +
geom_boxplot(alpha = 0.65, width = 0.6) +
geom_jitter(
width = 0.12,
size = 2.4,
color = "black",
alpha = 0.75
) +
stat_summary(
fun = mean,
geom = "point",
shape = 23,
size = 4,
fill = "white"
) +
labs(
title = "Contenido de vitamina C por tratamiento",
x = "Metodo de conservacion",
y = "Vitamina C (mg/100 mL)"
) +
theme_minimal() +
theme(legend.position = "none")
print(grafico_boxplot)
ggsave(
"boxplot_DBCA_vitamina_c.png",
grafico_boxplot,
width = 8,
height = 6,
dpi = 300
)
grafico_medias <- ggplot(
descriptivos_tratamiento,
aes(x = tratamiento, y = media, fill = tratamiento)
) +
geom_col(width = 0.6, alpha = 0.7) +
geom_errorbar(
aes(
ymin = media - error_estandar,
ymax = media + error_estandar
),
width = 0.2
) +
labs(
title = "Media de vitamina C por tratamiento",
subtitle = "Barras de error: ± error estandar",
x = "Tratamiento",
y = "Vitamina C (mg/100 mL)"
) +
theme_minimal() +
theme(legend.position = "none")
print(grafico_medias)
ggsave(
"medias_DBCA_vitamina_c.png",
grafico_medias,
width = 8,
height = 6,
dpi = 300
)
grafico_bloques <- ggplot(
datos,
aes(
x = tratamiento,
y = vitamina_c,
group = bloque,
color = bloque
)
) +
geom_line(alpha = 0.65) +
geom_point(size = 2.5) +
labs(
title = "Variacion de la respuesta dentro de cada bloque",
x = "Tratamiento",
y = "Vitamina C (mg/100 mL)",
color = "Bloque"
) +
theme_minimal()
print(grafico_bloques)
ggsave(
"perfil_bloques_DBCA.png",
grafico_bloques,
width = 8,
height = 6,
dpi = 300
)
Este último gráfico permite observar si hay diferencias sistemáticas entre bloques. Si todas las líneas están desplazadas hacia arriba o hacia abajo, puede existir un efecto del día de análisis.
# ============================================================
# MODELO DEL DISEÑO EN BLOQUES COMPLETOS AL AZAR
# ============================================================
modelo_dbca <- aov(
vitamina_c ~ tratamiento + bloque,
data = datos
)
summary(modelo_dbca)
La fórmula contiene:
vitamina_c ~ tratamiento + bloque
El orden de los términos no cambia el modelo aditivo en este caso, pero se recomienda colocar primero el tratamiento de interés:
vitamina_c ~ tratamiento + bloque
No se debe utilizar:
aov(vitamina_c ~ tratamiento * bloque, data = datos)
cuando existe una sola observación por combinación tratamiento × bloque. En ese caso no quedan grados de libertad suficientes para estimar adecuadamente una interacción independiente. Para el DBCA clásico se utiliza el modelo aditivo:
aov(respuesta ~ tratamiento + bloque, data = datos)
library(openxlsx)
tabla_anova <- anova(modelo_dbca)
# Convertir la tabla a data frame
tabla_anova_exportar <- as.data.frame(tabla_anova)
# Exportar a Excel con nombres de fila
write.xlsx(tabla_anova_exportar,
file = "tabla_ANOVA_DBCA_vitamina_c.xlsx",
sheetName = "ANOVA",
rowNames = TRUE)
La tabla ANOVA tendrá, conceptualmente, la siguiente estructura:
| Fuente de variación | Grados de libertad |
|---|---|
| Tratamiento | \(t-1=2\) |
| Bloque | \(b-1=7\) |
| Error | \((t-1)(b-1)=14\) |
| Total | \(tb-1=23\) |
El estadístico F para tratamientos evalúa si existen diferencias en la media de vitamina C después de descontar la variabilidad atribuida a los bloques.
# ============================================================
# NORMALIDAD DE LOS RESIDUOS
# ============================================================
residuos <- residuals(modelo_dbca)
shapiro_resultado <- shapiro.test(residuos)
print(shapiro_resultado)
qqnorm(
residuos,
main = "Gráfico Q-Q de residuos del DBCA"
)
qqline(
residuos,
col = "red",
lwd = 2
)
La prueba debe complementarse con el gráfico Q-Q.
# ============================================================
# HOMOCEDASTICIDAD
# ============================================================
levene_resultado <- leveneTest(
vitamina_c ~ tratamiento,
data = datos
)
print(levene_resultado)
plot(
modelo_dbca,
which = 1,
main = "Residuos vs. valores ajustados"
)
También debe observarse el gráfico de residuos:
La independencia no se verifica solamente con una prueba estadística. Se garantiza principalmente mediante:
par(mfrow = c(2, 2))
plot(modelo_dbca)
par(mfrow = c(1, 1))
Los cuatro gráficos habituales son:
La prueba de Tukey se aplica para determinar qué pares de tratamientos difieren cuando el ANOVA para tratamientos resulta significativo. Controla el error familiar asociado a las comparaciones múltiples.56
TukeyHSD()# ============================================================
# PRUEBA DE TUKEY
# ============================================================
tukey_dbca <- TukeyHSD(
modelo_dbca,
which = "tratamiento",
conf.level = 0.95
)
print(tukey_dbca)
plot(
tukey_dbca,
las = 1,
col = "steelblue"
)
El resultado contiene:
En un DBCA, las medias ajustadas pueden obtenerse con el paquete
emmeans. Esta opción es especialmente clara para comunicar
resultados.
# ============================================================
# MEDIAS AJUSTADAS Y TUKEY CON EMMEANS
# ============================================================
medias_ajustadas <- emmeans(
modelo_dbca,
~ tratamiento
)
print(medias_ajustadas)
comparaciones_tukey <- pairs(
medias_ajustadas,
adjust = "tukey"
)
print(comparaciones_tukey)
intervalos_tukey <- confint(
comparaciones_tukey
)
print(intervalos_tukey)
# Obtener letras de agrupamiento
grupos_tukey <- cld(
medias_ajustadas,
adjust = "tukey",
Letters = letters
)
print(grupos_tukey)
Según la versión instalada de emmeans, puede ser
necesario cargar:
library(multcomp)
library(multcompView)
La tabla de letras permite interpretar los resultados:
| Tratamiento | Media ajustada | Grupo |
|---|---|---|
| T3 | 53.2 | a |
| T2 | 49.9 | ab |
| T1 | 44.3 | b |
La interpretación sería:
grafico_emmeans <- plot(
medias_ajustadas,
comparisons = TRUE
) +
labs(
title = "Medias ajustadas de vitamina C",
x = "Vitamina C (mg/100 mL)",
y = "Tratamiento"
) +
theme_minimal()
print(grafico_emmeans)
También puede realizarse un gráfico personalizado:
medias_ajustadas_df <- as.data.frame(medias_ajustadas)
ggplot(
medias_ajustadas_df,
aes(x = tratamiento, y = emmean)
) +
geom_point(size = 4, color = "steelblue") +
geom_errorbar(
aes(ymin = lower.CL, ymax = upper.CL),
width = 0.15,
linewidth = 0.9
) +
labs(
title = "Medias ajustadas e intervalos de confianza",
x = "Tratamiento",
y = "Vitamina C (mg/100 mL)"
) +
theme_minimal()
Puede compararse la variabilidad residual del DBCA con la de un DCA:
# Modelo como diseño completamente aleatorizado
modelo_dca <- aov(
vitamina_c ~ tratamiento,
data = datos
)
# Modelo como DBCA
modelo_dbca <- aov(
vitamina_c ~ tratamiento + bloque,
data = datos
)
# Cuadrados medios del error
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")
# Porcentaje de reducción del error
reduccion_error <- (mse_dca - mse_dbca) / mse_dca * 100
cat(
"Reduccion porcentual del error:",
round(reduccion_error, 2),
"%\n"
)
Si el MSE del DBCA es menor que el MSE del DCA, el bloqueo logró explicar parte de la variabilidad no deseada.
Un bloqueo es útil cuando:
Si todos los bloques son prácticamente iguales, el bloqueo puede no aportar ventajas. Si los bloques son demasiado heterogéneos internamente, el diseño tampoco será eficiente.
El siguiente script resume todo el análisis:
# ============================================================
# SCRIPT COMPLETO: DBCA VITAMINA C
# ============================================================
# ============================================================
# ANÁLISIS ESTADÍSTICO DE UN DBCA
# Vitamina C en jugo de naranja
# ============================================================
# Instalar una sola vez, si fuera necesario
# install.packages(c(
# "readxl", "openxlsx", tidyverse", "janitor", "car",
# "emmeans", "agricolae", "writexl", "broom", "multcomp", "multcompView"
# ))
library(readxl)
library(tidyverse)
library(janitor)
library(car)
library(emmeans)
library(agricolae)
library(writexl)
library(broom)
library(openxlsx)
library(multcomp)
library(multcompView)
# 1. Importar datos desde Excel
datos_raw <- read_excel(
"datos_vitamina_c_DBCA.xlsx",
sheet = "Datos_Raw"
)
# Limpiar nombres de columnas
datos <- datos_raw %>%
clean_names()
# Revisar nombres originales después de clean_names()
names(datos)
# Adaptar estos nombres si la planilla fue creada con nombres diferentes
datos <- datos %>%
rename(
ue = ue,
bloque = bloque,
orden_analisis = orden_analisis,
tratamiento = tratamiento,
temp_conservacion = temp_conservacion_c,
volumen_dcpip = vol_dcpip_m_l,
vitamina_c = vitamina_c_mg100m_l
)
# Convertir variables categóricas a factores
datos <- datos %>%
mutate(
ue = factor(ue),
bloque = factor(bloque),
tratamiento = factor(
tratamiento,
levels = c("T1_25C", "T2_4C", "T3_menos5C")
),
orden_analisis = as.numeric(orden_analisis),
vitamina_c = as.numeric(vitamina_c)
)
# 2. Revisar estructura
str(datos)
summary(datos)
# Comprobar valores faltantes
colSums(is.na(datos))
# Comprobar cantidad de unidades
nrow(datos)
# Comprobar balance del DBCA
with(datos, table(bloque, tratamiento))
# ============================================================
# ESTADÍSTICA DESCRIPTIVA
# ============================================================
# 3. Estadística descriptiva
descriptivos_tratamiento <- 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),
coeficiente_variacion =
desviacion_estandar / media * 100,
minimo = min(vitamina_c),
maximo = max(vitamina_c),
cuartil_1 = quantile(vitamina_c, 0.25),
cuartil_3 = quantile(vitamina_c, 0.75)
)
print(descriptivos_tratamiento)
descriptivos_bloque <- datos %>%
group_by(bloque) %>%
summarise(
n = n(),
media = mean(vitamina_c),
desviacion_estandar = sd(vitamina_c)
)
print(descriptivos_bloque)
# Exportar descriptivos
write_xlsx(
list(
Descriptivos_Tratamiento = descriptivos_tratamiento,
Descriptivos_Bloque = descriptivos_bloque
),
"descriptivos_DBCA_vitamina_c.xlsx"
)
# 4. Graficos exploratorios
# Boxplot por tratamiento
grafico_boxplot <- ggplot(
datos,
aes(x = tratamiento, y = vitamina_c, fill = tratamiento)
) +
geom_boxplot(alpha = 0.65, width = 0.6) +
geom_jitter(
width = 0.12,
size = 2.4,
color = "black",
alpha = 0.75
) +
stat_summary(
fun = mean,
geom = "point",
shape = 23,
size = 4,
fill = "white"
) +
labs(
title = "Contenido de vitamina C por tratamiento",
x = "Metodo de conservacion",
y = "Vitamina C (mg/100 mL)"
) +
theme_minimal() +
theme(legend.position = "none")
print(grafico_boxplot)
ggsave(
"boxplot_DBCA_vitamina_c.png",
grafico_boxplot,
width = 8,
height = 6,
dpi = 300
)
# grafico de medias por tratamiento
grafico_medias <- ggplot(
descriptivos_tratamiento,
aes(x = tratamiento, y = media, fill = tratamiento)
) +
geom_col(width = 0.6, alpha = 0.7) +
geom_errorbar(
aes(
ymin = media - error_estandar,
ymax = media + error_estandar
),
width = 0.2
) +
labs(
title = "Media de vitamina C por tratamiento",
subtitle = "Barras de error: ± error estandar",
x = "Tratamiento",
y = "Vitamina C (mg/100 mL)"
) +
theme_minimal() +
theme(legend.position = "none")
print(grafico_medias)
ggsave(
"medias_DBCA_vitamina_c.png",
grafico_medias,
width = 8,
height = 6,
dpi = 300
)
# visualizacion por bloque
grafico_bloques <- ggplot(
datos,
aes(
x = tratamiento,
y = vitamina_c,
group = bloque,
color = bloque
)
) +
geom_line(alpha = 0.65) +
geom_point(size = 2.5) +
labs(
title = "Variacion de la respuesta dentro de cada bloque",
x = "Tratamiento",
y = "Vitamina C (mg/100 mL)",
color = "Bloque"
) +
theme_minimal()
print(grafico_bloques)
ggsave(
"perfil_bloques_DBCA.png",
grafico_bloques,
width = 8,
height = 6,
dpi = 300
)
# ============================================================
# MODELO DEL DISEÑO EN BLOQUES COMPLETOS AL AZAR
# ============================================================
# 5. Modelo DBCA
modelo_dbca <- aov(
vitamina_c ~ tratamiento + bloque,
data = datos
)
summary(modelo_dbca)
# 6. ANOVA
library(openxlsx)
tabla_anova <- anova(modelo_dbca)
# Convertir la tabla a data frame
tabla_anova_exportar <- as.data.frame(tabla_anova)
# Exportar a Excel con nombres de fila
write.xlsx(tabla_anova_exportar,
file = "tabla_ANOVA_DBCA_vitamina_c.xlsx",
sheetName = "ANOVA",
rowNames = TRUE)
# ============================================================
# NORMALIDAD DE LOS RESIDUOS
# ============================================================
# 7. Residuos
residuos <- residuals(modelo_dbca)
# 8. Normalidad
shapiro_resultado <- shapiro.test(residuos)
print(shapiro_resultado)
qqnorm(
residuos,
main = "Gráfico Q-Q de residuos del DBCA"
)
qqline(
residuos,
col = "red",
lwd = 2
)
# ============================================================
# HOMOCEDASTICIDAD
# ============================================================
# 9. Homogeneidad de varianzas
levene_resultado <- leveneTest(
vitamina_c ~ tratamiento,
data = datos
)
print(levene_resultado)
plot(
modelo_dbca,
which = 1,
main = "Residuos vs. valores ajustados"
)
# 10. grafico diagnosticos integrados
par(mfrow = c(2, 2))
plot(modelo_dbca)
par(mfrow = c(1, 1))
# ============================================================
# PRUEBA DE TUKEY
# ============================================================
# 11. Tukey
tukey_dbca <- TukeyHSD(
modelo_dbca,
which = "tratamiento",
conf.level = 0.95
)
print(tukey_dbca)
plot(
tukey_dbca,
las = 1,
col = "steelblue"
)
# ============================================================
# MEDIAS AJUSTADAS Y TUKEY CON EMMEANS
# ============================================================
# 12. Medias ajustadas
medias_ajustadas <- emmeans(
modelo_dbca,
~ tratamiento
)
print(medias_ajustadas)
# 13. Comparaciones de Tukey
comparaciones_tukey <- pairs(
medias_ajustadas,
adjust = "tukey"
)
print(comparaciones_tukey)
intervalos_tukey <- confint(
comparaciones_tukey
)
print(intervalos_tukey)
# 14. Obtener letras de agrupamiento
library(multcomp)
library(multcompView)
grupos_tukey <- cld(
medias_ajustadas,
adjust = "tukey",
Letters = letters
)
print(grupos_tukey)
# 15. grafico de medias ajustadas
grafico_emmeans <- plot(
medias_ajustadas,
comparisons = TRUE
) +
labs(
title = "Medias ajustadas de vitamina C",
x = "Vitamina C (mg/100 mL)",
y = "Tratamiento"
) +
theme_minimal()
print(grafico_emmeans)
# grafico personalizado
medias_ajustadas_df <- as.data.frame(medias_ajustadas)
ggplot(
medias_ajustadas_df,
aes(x = tratamiento, y = emmean)
) +
geom_point(size = 4, color = "steelblue") +
geom_errorbar(
aes(ymin = lower.CL, ymax = upper.CL),
width = 0.15,
linewidth = 0.9
) +
labs(
title = "Medias ajustadas e intervalos de confianza",
x = "Tratamiento",
y = "Vitamina C (mg/100 mL)"
) +
theme_minimal()
# 16. Eficiencia del bloqueo
# Modelo como diseño completamente aleatorizado
modelo_dca <- aov(
vitamina_c ~ tratamiento,
data = datos
)
# Modelo como DBCA
modelo_dbca <- aov(
vitamina_c ~ tratamiento + bloque,
data = datos
)
# Cuadrados medios del error
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")
# Porcentaje de reducción del error
reduccion_error <- (mse_dca - mse_dbca) / mse_dca * 100
cat(
"Reduccion porcentual del error:",
round(reduccion_error, 2),
"%\n"
)
En un DBCA, la pregunta no es únicamente:
“¿Qué tratamiento tiene la media más alta?”
La pregunta correcta es:
“¿Existen diferencias entre los métodos de conservación una vez que se ha controlado la variabilidad producida por los días o bloques de análisis?”
Esa es la principal ventaja del diseño: separar, en la medida de lo posible, la variación atribuible al tratamiento de la variación producida por una fuente conocida de heterogeneidad.
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 en Bloques Completos al Azar (DBCA). Universidad Nacional de Jujuy. Material docente elaborado con apoyo de inteligencia artificial.
https://r-statistics.co/Randomized-Complete-Block-Design-in-R.html↩︎
https://www.rdocumentation.org/packages/randomizr/versions/1.0.1/topics/block_ra↩︎
https://r-statistics.co/Experimental-Design-Exercises-in-R.html↩︎
https://wpd.ugr.es/~bioestad/diseno-estadistico-de-experimentos/tema-2/↩︎
https://r-statistics.co/Randomized-Complete-Block-Design-in-R.html↩︎
https://es.scribd.com/document/900367246/Diseno-de-bloques-completos-al-azar-con-arreglo-factorial-Kempthorne-1952↩︎
https://samuelbfernandes.github.io/agst50104-lectures/lecture06_week04.html↩︎
https://www.slideshare.net/slideshow/comprehensive-guide-to-randomized-complete-block-design-rcbd-in-experimental-statistics/286903907↩︎
https://pt.scribd.com/document/801151228/karen-colaborativo-fase-2↩︎
https://cran.r-project.org/web/packages/randotools/refman/randotools.html↩︎
https://www.rdocumentation.org/packages/psych/versions/2.6.1/topics/block.random↩︎
https://www.rdocumentation.org/packages/pwr4exp/versions/1.0.1/topics/df.rcbd↩︎