Ejercicio de Clase — Consola de R

Probabilidad Condicional y Tablas de Contingencia con un Experimento Real de Fertilización

Asignatura: Estadística Aplicada con Python y R — Semana 5 (Probabilidad Condicional y Tablas de Contingencia)

Modalidad: Consola de R en vivo (Posit Cloud), individual o en parejas

Dataset: yates.oats, paquete agridat — experimento real de parcelas divididas (Rothamsted, 1931): 3 variedades de avena × 4 dosis de nitrógeno × 6 bloques = 72 observaciones

Entregable: Historial de comandos de R para el RMarkdown/RPubs


Contexto

En 1931, en la Estación Experimental de Rothamsted (Inglaterra), se sembraron 3 variedades de avena (Golden Rain, Marvellous, Victory) en 6 bloques. Dentro de cada bloque, cada variedad se dividió en 4 subparcelas, y a cada subparcela se le asignó al azar una dosis de nitrógeno: 0, 0.2, 0.4 o 0.6 cwt/acre (un diseño de “parcela dividida” o split-plot). Se midió el rendimiento de grano de cada subparcela. Es uno de los conjuntos de datos más citados en el diseño de experimentos agrícolas — lo volverán a ver, con ANOVA de parcelas divididas, en tu curso de Diseño Experimental.


Objetivos de la sesión

  • Instalar y cargar un paquete de R con un dataset real de interés agrícola.
  • Distinguir cuándo existe un criterio de recodificación establecido (dado por el propio diseño del experimento) de cuándo hay que recurrir a un criterio estadístico (tercer cuartil).
  • Construir una tabla de contingencia 2×2 y calcular varias probabilidades condicionales en ambas direcciones.
  • Aplicar chisq.test() — con y sin corrección de Yates, porque ahora sí es una tabla 2×2 — e interpretar correctamente el resultado.
  • Distinguir con precisión asociación estadística de causalidad, y entender por qué aquí el argumento causal es más sólido que con Soils.

Parte A — Instalar y cargar el paquete y el dataset

install.packages("agridat")
library(agridat)

data(yates.oats)
str(yates.oats)
head(yates.oats)
nrow(yates.oats)
table(yates.oats$nitro)   # las 4 dosis, 18 observaciones cada una
table(yates.oats$gen)     # las 3 variedades, 24 observaciones cada una

Si los nombres de columna difieren levemente en tu versión del paquete (names(yates.oats)), ajusta el resto del código con esos nombres — la lógica no cambia.


Parte B — Recodificar: ¿hay o no un criterio establecido?

B1. nitro — aquí SÍ hay un criterio establecido (no estadístico): lo fijó el experimento

A diferencia del pH (donde el criterio lo da la agronomía), aquí el criterio lo da el propio diseño experimental: una subparcela recibió nitrógeno o no lo recibió. No hace falta inventar un punto de corte:

yates.oats$nitro_nivel <- ifelse(yates.oats$nitro == 0, "Sin_N", "Con_N")
yates.oats$nitro_nivel <- factor(yates.oats$nitro_nivel, levels = c("Sin_N", "Con_N"))

table(yates.oats$nitro_nivel)

B2. yield (rendimiento) — aquí NO hay un umbral agronómico universal → tercer cuartil

No existe un estándar único de “rendimiento alto/bajo” en avena (depende de variedad, época, unidades). Se sigue tu regla: todo lo que supere Q3 se clasifica como Alto.

q3_yield <- quantile(yates.oats$yield, probs = 0.75)
q3_yield

yates.oats$yield_nivel <- ifelse(yates.oats$yield > q3_yield, "Alto", "Bajo")
yates.oats$yield_nivel <- factor(yates.oats$yield_nivel, levels = c("Bajo", "Alto"))

table(yates.oats$yield_nivel)

Referencia: Q3 ≈ 121.25; esto deja 18 observaciones en “Alto” y 54 en “Bajo” (exactamente 25%/75%, por definición de cuartil).


Parte C — La tabla de contingencia

tabla <- table(yates.oats$nitro_nivel, yates.oats$yield_nivel)
tabla
addmargins(tabla)

Salida de referencia (verificada):

        Bajo Alto
 Sin_N    18    0
 Con_N    36   18

Totales de fila: Sin_N = 18, Con_N = 54. Totales de columna: Bajo = 54, Alto = 18. Gran total = 72.


Parte D — Varias probabilidades condicionales

# Condicional por fila: dado el nivel de nitrógeno, ¿qué tan probable es cada nivel de rendimiento?
prop.table(tabla, margin = 1)

# Condicional por columna: dado el nivel de rendimiento, ¿qué tan probable es cada nivel de nitrógeno?
prop.table(tabla, margin = 2)

# Conjunta
prop.table(tabla)

Referencia: - \(P(\text{Alto} \mid \text{Sin\_N}) = 0.000\) — ninguna subparcela sin nitrógeno alcanzó rendimiento alto. - \(P(\text{Alto} \mid \text{Con\_N}) = 0.333\) — una de cada tres subparcelas fertilizadas sí lo alcanzó. - \(P(\text{Con\_N} \mid \text{Alto}) = 1.000\) — el 100% de las subparcelas de rendimiento alto habían recibido nitrógeno. - \(P(\text{Sin\_N} \mid \text{Bajo}) = 0.333\).

Pregunta para la clase: \(P(\text{Alto}\mid\text{Con\_N})=0.333\) y \(P(\text{Con\_N}\mid\text{Alto})=1.000\) — ¿por qué son tan distintas si ambas “involucran” a Con_N y a Alto? (Dividen entre denominadores distintos: la primera entre el total de subparcelas fertilizadas [54], la segunda entre el total de subparcelas con rendimiento alto [18].)


Parte E — Chi-cuadrado: asociación, corrección de Yates y causalidad

chisq.test(tabla, correct = TRUE)    # con corrección de Yates (default, tabla 2x2)
chisq.test(tabla, correct = FALSE)   # sin corrección

Referencia: χ² = 8.00 (sin corrección) vs. χ² = 6.32 (con corrección de Yates), gl = 1, p = 0.0047 y p = 0.0119 respectivamente — ambos significativos a 0.05, pero nótese cuánto cambia el valor exacto: aquí, a diferencia de las tablas 3×3 de la sesión anterior, la corrección importa, porque solo aplica a tablas 2×2. Una celda tiene frecuencia esperada de 4.5 (ligeramente bajo el criterio informal de 5); como verificación adicional, fisher.test(tabla) da p ≈ 0.0036, confirmando la conclusión.

Asociación vs. causalidad — ahora con más matices que con Soils

Aquí el argumento causal es más fuerte que en el ejercicio anterior, por una razón concreta: la dosis de nitrógeno fue asignada al azar a cada subparcela por el experimentador (no la eligió el suelo ni el agricultor). Eso es justamente lo que permite, en principio, interpretar una asociación como evidencia de causalidad — es la lógica central de tu curso de Diseño Experimental.

Pero hay que ser precisos:

  • “La aleatorización del nitrógeno, junto con una asociación significativa, es coherente con un efecto causal del nitrógeno sobre el rendimiento.”
  • ⚠️ Esta tabla 2×2 colapsó los datos ignorando el bloque y la variedad — dos fuentes de variación que el diseño original sí controla. La prueba χ² sobre esta tabla simplificada no aísla el efecto del nitrógeno de esas otras fuentes; eso exige exactamente el ANOVA de parcelas divididas (aov(yield ~ block + gen*nitro, ...)) que se cubre en Diseño Experimental.

Pregunta de cierre: ¿qué le da más fuerza causal a este experimento frente a Soils: el valor del p-valor, o el hecho de que el nitrógeno se asignó al azar? (La aleatorización — un p-valor pequeño en un estudio observacional como Soils nunca deja de ser observacional.)


Parte F — Extra/opcional: ¿y la variedad?

tabla_gen <- table(yates.oats$gen, yates.oats$yield_nivel)
tabla_gen
chisq.test(tabla_gen)
prop.table(tabla_gen, margin = 1)

Referencia: χ² ≈ 1.33, gl = 2, p ≈ 0.513 — no hay evidencia de asociación entre variedad y nivel de rendimiento. Buen contraste para la clase: no toda variable produce una tabla significativa; aquí el nitrógeno sí importa, la variedad (en este análisis simplificado) no.


Parte G — Recolectar el Historial de R

history(max.show = Inf)
savehistory(file = "Semana5_YatesOats_Consola.Rhistory")

O en RStudio/Posit Cloud: pestaña History → seleccionar todo → To Source. Ese bloque limpio se pega como chunk de R en el .Rmd para KnitPublish a RPubs.


Nota para ti

Te recomiendo correr esto una vez antes de clase: aunque verifiqué los 72 valores contra el dataset original publicado (Yates 1935 / Rothamsted Report), la forma exacta en que agridat etiqueta gen (nombres completos vs. abreviados) puede variar levemente entre versiones del paquete — un detalle menor que str() resuelve al instante.