Módulo 8: Project Measure Mercados Recommendations Launch
Dimensiona el experimento: ¿la muestra alcanzaba?
Descripción
Los módulos 5 y 6 —y las lecciones 2 a 4 de este capstone— trabajaron con una muestra ya fija: 12,000 usuarios por variante, el número que el experimento de recommendations terminó acumulando en sus seis semanas. Nadie, hasta ahora, preguntó si ese número alcanzaba. Esta lección hace esa pregunta al revés de como se hizo hasta ahora: en vez de partir de los datos que ya existen, vas a calcular, con la fórmula estándar de tamaño de muestra para proporciones, cuántos usuarios por variante hacían falta para poder confiar en el resultado — y después vas a comparar ese número contra los 12,000 reales.
Conexión con el módulo. Esta es la cuarta capa del método completo, y la primera de este capstone que retoma el módulo 7 —construido en paralelo a este mismo texto—. Reutiliza sampleSize({ baseline, mde, alpha, power }) con la misma fórmula, sin aproximar (p1*(1-p1) + p2*(1-p2), la varianza exacta de cada proporción, no 2*p*(1-p)) y el mismo MDE relativo pre-registrado, 20%, que el módulo 7 usa en su lección 3 y en la auditoría de la lección 8 — no una variante propia de este capstone, la fórmula y el umbral idénticos, aplicados sobre el mismo checkoutConversionRate de las lecciones anteriores. El resultado de esta lección es el que responde una pregunta que las lecciones 5 y 6 del método (más adelante en este capstone) necesitan como base: cuando el z-test diga "significativo", ¿fue porque la muestra estaba bien dimensionada, o porque tuvimos suerte con una muestra insuficiente?
Una analogía: cuántos tiros hacen falta para confiar en la moneda
Si quieres confirmar que una moneda está apenas cargada —cae cara el 53% de las veces, en vez del 50% esperado—, tirarla 10 veces no alcanza: la diferencia entre 5 y 6 caras de 10 tiros es del todo compatible con una moneda perfectamente justa, pura casualidad de muestreo. Necesitas muchísimos más tiros —cientos, quizás miles— para que un sesgo tan chico (apenas 3 puntos porcentuales) se distinga, con confianza, del ruido normal de tirar una moneda. Cuanto más chico es el sesgo que quieres detectar, más tiros hacen falta. El tamaño de muestra de un A/B test obedece exactamente la misma lógica: cuanto más chico es el efecto que te interesa detectar (el MDE, mínimo efecto detectable), más usuarios por variante necesitas para poder confiar en el resultado.
Ejemplo trabajado: sampleSize() sobre el experimento de recommendations
Antes de lanzar recommendations como A/B test, el equipo de Mercado tenía que decidir cuántas semanas correr el experimento — y esa decisión depende de cuántos usuarios por variante hacen falta para confiar en el resultado. Siguiendo la misma disciplina de protocolo del módulo 5 y del módulo 7 (lección 2): el efecto mínimo que justificaría mantener el carrusel en producción se fijó, de antemano, en un MDE de 20% relativo sobre la tasa base de conversión de checkout (3.2%) — el mismo umbral pre-registrado que la auditoría del módulo 7 usa para calcular cuánta muestra hacía falta.
// sampleSize: formula estandar de tamano de muestra para dos proporciones, EXACTAMENTE
// la misma formula del modulo 7 (leccion 3) -- varianza EXACTA de cada proporcion,
// p1*(1-p1) + p2*(1-p2), no la aproximacion 2*p*(1-p). z_alpha/2 = 1.96 (alpha = 0.05,
// dos colas) y z_beta = 0.84 (power = 0.80), los mismos valores criticos fijos que ya usa
// abTest() para el intervalo de confianza del 95% (modulo 6).
//
// n = (z_alpha/2 + z_beta)^2 * (p1*(1-p1) + p2*(1-p2)) / (p2-p1)^2 -- p2 = baseline *
// (1 + mde), el MDE expresado como fraccion RELATIVA sobre el baseline, la misma
// convencion del modulo 7.
function sampleSize({ baseline, mde, alpha = 0.05, power = 0.8 }) {
const zAlpha2 = 1.96; // z critico para alpha = 0.05, dos colas
const zBeta = 0.84; // z critico para power = 0.80
const p1 = baseline;
const p2 = baseline * (1 + mde);
const n = Math.pow(zAlpha2 + zBeta, 2) * (p1 * (1 - p1) + p2 * (1 - p2)) / Math.pow(p2 - p1, 2);
return { requiredPerVariant: Math.ceil(n), zAlpha2, zBeta, baseline, mde, alpha, power };
}
function fmt(n) {
return String(n).replace(/\B(?=(\d{3})+(?!\d))/g, ',');
}
console.log('=== sampleSize: cuantos usuarios por variante hacian falta ===\n');
const sizing = sampleSize({ baseline: 0.032, mde: 0.20, alpha: 0.05, power: 0.8 });
console.log('baseline (checkoutConversionRate de control): ' + (sizing.baseline * 100).toFixed(1) + '%');
console.log('MDE pre-registrado (el mismo del modulo 7): ' + (sizing.mde * 100).toFixed(0) + '% relativo' +
' (' + (sizing.baseline * sizing.mde * 100).toFixed(2) + 'pp sobre el baseline)');
console.log('alpha = ' + sizing.alpha + ' (z_alpha/2 = ' + sizing.zAlpha2 + ') power = ' + sizing.power + ' (z_beta = ' + sizing.zBeta + ')');
console.log('\nUsuarios requeridos por variante: ' + fmt(sizing.requiredPerVariant));
const actualN = 12000;
console.log('\nMuestra real usada en el experimento (modulo 5): ' + fmt(actualN) + ' por variante');
const diff = actualN - sizing.requiredPerVariant;
console.log('Diferencia: ' + fmt(diff) + ' usuarios por variante ' +
(diff >= 0 ? '(la muestra ALCANZABA)' : '(la muestra quedo POR DEBAJO del ideal)'));
Qué esperar. Al correr el archivo con Node, la salida es exactamente esta:
=== sampleSize: cuantos usuarios por variante hacian falta ===
baseline (checkoutConversionRate de control): 3.2%
MDE pre-registrado (el mismo del modulo 7): 20% relativo (0.64pp sobre el baseline)
alpha = 0.05 (z_alpha/2 = 1.96) power = 0.8 (z_beta = 0.84)
Usuarios requeridos por variante: 12,997
Muestra real usada en el experimento (modulo 5): 12,000 por variante
Diferencia: -997 usuarios por variante (la muestra quedo POR DEBAJO del ideal)
Leyendo el resultado: ligeramente por debajo del ideal, y por qué eso importa
El cálculo confirma, con la misma fórmula y el mismo MDE que usa el módulo 7, algo que ninguna de las lecciones anteriores de este capstone había verificado: hacían falta 12,997 usuarios por variante para detectar, con 80% de poder, el MDE pre-registrado de 20% relativo sobre una base de 3.2% — y la muestra real, 12,000, quedó por debajo de ese número, un déficit de 997 usuarios por variante, poco menos del 8%. No es un margen de sobra: es un experimento que corrió con ligeramente menos muestra de la que su propio diseño exigía.
Esto no invalida el resultado que vas a confirmar formalmente en la lección 6 —el z-test dio significativo, con p ≈ 0.0114—, pero le cambia el peso: no es la clase de "significativo" que llega con un colchón de seguridad de sobra sobre el mínimo requerido, es un resultado que salió adelante con un margen estrecho, exactamente el tipo de caso que el módulo 7 —en su propia auditoría de este mismo experimento, en la lección 8 de ese módulo— identifica como "funcionó, pero no por un diseño con margen de sobra: funcionó porque el efecto real que apareció (18.75% de lift) resultó ser lo bastante grande como para cruzar el umbral de significancia de todas formas, a pesar del déficit frente al MDE pre-registrado".
Fíjate, también, en algo que la fórmula deja ver con claridad: si el equipo hubiera querido detectar un efecto más chico, digamos un MDE de 10% relativo (la mitad de 20%), la muestra requerida sube a 49,718 por variante —casi cuatro veces más, no el doble— porque el denominador de la fórmula ((p2-p1)²) crece cuadráticamente cuando el MDE se reduce a la mitad. Esa es la razón matemática, no solo intuitiva, detrás de la advertencia central del módulo 7: detectar un efecto chico exige, de forma desproporcionada, mucha más muestra que detectar uno grande — y es, en sentido inverso, la misma razón por la que el déficit de hoy (997 usuarios, menos del 8% por debajo del ideal) es un margen estrecho pero no catastrófico: MDE=20% está lo bastante lejos de MDE=10% o 5% como para que un déficit chico en n no arruine automáticamente la capacidad de detectar el efecto, si ese efecto termina siendo, como pasó aquí, más grande que el MDE mínimo.
Profundización: qué asume esta fórmula, y dónde puede fallar
La fórmula usada aquí calcula la varianza combinada de control y variant de forma exacta — p1*(1-p1) + p2*(1-p2), la varianza real de cada proporción sumada, sin la aproximación 2*p*(1-p) que asume que p1 y p2 son casi idénticos (una simplificación razonable solo cuando el MDE es muy chico en términos absolutos). Es, sin ningún cambio, la misma fórmula que el módulo 7 usa en su lección 3 y en la auditoría de su lección 8 — por eso esta lección llega al mismo número, 12,997, que esa auditoría. También asume que los z críticos (1.96 y 0.84) corresponden exactamente a alpha = 0.05 (dos colas) y power = 0.80 — los valores convencionales de la industria, los mismos que cita el módulo 7. Cambiar alpha o power cambiaría esos valores críticos (un test más exigente, con alpha = 0.01, usaría un z_alpha/2 más grande, y pediría más muestra); esta lección, siguiendo la convención del módulo 7, los deja fijos en sus valores más comunes, no los recalcula de forma general.
Vale la pena decir, también, algo que esta lección no resuelve: el cálculo de hoy usa baseline = 0.032, la tasa de control observada al final del experimento. En la práctica, un equipo real tiene que estimar esa baseline antes de correr el experimento, normalmente con datos históricos —como los que viste en la lección 3 de este capstone, o en el módulo 1—. Si esa estimación previa hubiera estado mal (por ejemplo, si el equipo hubiera asumido una baseline de 4% en vez de 3.2%), el tamaño de muestra calculado de antemano habría sido distinto. La lección 8 —el proyecto final— retoma esta idea al construir el reporte completo del experimento.
Errores comunes
Calcular el tamaño de muestra después de tener el resultado, en vez de antes de correr el experimento. Qué pasa: alguien corre sampleSize() solo al final, como un chequeo retroactivo de "¿nos alcanzó?", en vez de calcularlo antes de lanzar el experimento y usarlo para decidir cuántas semanas correrlo. Por qué pasa: es más fácil verificar un número que ya existe (12,000) que comprometerse, de antemano, a una muestra objetivo sin saber todavía qué va a pasar. Cómo detectarlo: si nadie en el equipo puede decir cuál era el MDE objetivo antes de que el experimento arrancara, el cálculo de hoy se hizo al revés — como una justificación después del hecho, no como un plan. Cómo corregirlo: el orden correcto es exactamente el de esta lección — definir el MDE que justifica el costo (con el equipo de negocio, antes de ver ningún dato), calcular sampleSize(), y usar ese número para decidir cuánto tiempo correr el experimento. Verificarlo después, como hizo esta lección, sirve para auditar la disciplina del proceso — no reemplaza haberlo planeado de antemano.
Tratar un resultado significativo (p < 0.05) como evidencia de que la muestra "obviamente alcanzaba". Qué pasa: alguien ve que la lección 6 confirma significant: true (p ≈ 0.0114) y concluye que, como el resultado salió adelante, la muestra de 12,000 "tenía que haber sido suficiente" — sin correr sampleSize() para comparar contra el MDE pre-registrado. Por qué pasa: un resultado significativo se siente como una validación retroactiva de todas las decisiones que llevaron a él, incluyendo el tamaño de muestra. Cómo detectarlo: la justificación de que "el n fue suficiente" cita únicamente el p-value final, sin ningún cálculo de sampleSize() de respaldo. Cómo corregirlo: como muestra el resultado de hoy, la muestra real (12,000) quedó por debajo de los 12,997 que el MDE de 20% exigía — el resultado salió significativo de todas formas, pero eso no prueba que el diseño fuera el correcto; es evidencia de que, en este caso puntual, el efecto real fue lo bastante grande como para compensar una muestra ligeramente insuficiente. La única forma de saber si el n fue el correcto es comparar contra sampleSize(), calculado con el MDE pre-registrado — nunca con el p-value final como sustituto.
Elegir un MDE arbitrariamente chico "para estar más seguros", sin considerar el costo de muestra. Qué pasa: alguien argumenta que el equipo debería haber apuntado a detectar un MDE de 5% relativo, "para no dejar pasar ningún efecto, por chico que sea", sin calcular cuánta muestra —o cuánto tiempo— exigiría eso. Por qué pasa: un MDE más chico suena, intuitivamente, a "más riguroso", sin conectar esa intuición con el costo real en tiempo y usuarios que implica. Cómo detectarlo: si alguien propone un MDE sin correr sampleSize() para ver cuántos usuarios (o cuántas semanas) implica, la propuesta ignora el costo del rigor que está pidiendo. Cómo corregirlo: como muestra el ejemplo de esta lección (MDE=10% exige casi cuatro veces la muestra de MDE=20%, 49,718 contra 12,997), siempre corre sampleSize() antes de comprometerte a un MDE — el MDE correcto es el efecto más chico que de verdad justificaría, en negocio, mantener el cambio, no el número más chico que la curiosidad estadística pudiera desear.
Ejercicios
Ejercicio 1 — Recalcula con un MDE más exigente. Sin ejecutar Node todavía, ¿el tamaño de muestra requerido sube o baja si el equipo hubiera exigido un MDE de 30% relativo en vez de 20% (una decisión más exigente sobre el efecto mínimo que justifica el costo, según el criterio de la lección 2 del módulo 7)? Justifica tu respuesta con la fórmula, y después verifica corriendo sampleSize({ baseline: 0.032, mde: 0.30, alpha: 0.05, power: 0.8 }).
Ver solución
Baja. En la fórmula, mde determina la brecha p2 - p1 en el denominador, elevada al cuadrado — así que un MDE más grande (30% en vez de 20%) agranda esa brecha, reduciendo el tamaño de muestra requerido: un efecto más grande es más fácil de detectar con menos usuarios, exactamente lo opuesto de lo que muestra el ejemplo de esta lección al bajar el MDE a 10%. Al correr sampleSize({ baseline: 0.032, mde: 0.30, alpha: 0.05, power: 0.8 }), el resultado da requiredPerVariant: 6027 — menos de la mitad de los 12,997 necesarios para el MDE de 20%, y muy por debajo de los 12,000 reales, con margen de sobra.
Ejercicio 2 — Conecta con el guardrail de la lección 4. El guardrail roto de la lección 4 (checkoutLatencyP95Ms) sugiere que mantener recommendations tiene un costo técnico real. Si ese costo técnico fuera todavía mayor de lo que parece hoy, ¿debería el equipo subir o bajar el MDE objetivo del próximo experimento relacionado con recomendaciones? Explica el razonamiento de negocio, no solo el matemático.
Ver solución
Debería subir el MDE objetivo. Si mantener y escalar recommendations cuesta más caro en infraestructura (más servidores para bajar la latencia, más ingeniería para optimizar el motor de recomendaciones), el efecto mínimo que justifica ese costo también sube — ya no basta con un lift de 20% relativo para que la inversión valga la pena; podría hacer falta un lift de 30% o más para justificar el gasto adicional. Subir el MDE objetivo, a su vez, baja el tamaño de muestra requerido (como confirmó el Ejercicio 1) — una relación no siempre intuitiva: cuando el costo de negocio sube, el rigor estadístico necesario para justificarlo, medido en usuarios necesarios, en realidad baja, porque el efecto que hace falta detectar es más grande y más fácil de ver.
Ejercicio 3 — Diseña el tamaño de muestra de un experimento nuevo. Mercado quiere probar una segunda versión del carrusel de recomendaciones, esta vez basada en el historial de compras del usuario (no solo en el producto que está viendo). El equipo estima una baseline de 3.8% (la tasa de conversión de variant del experimento actual) y quiere detectar un MDE relativo de 10% —siguiendo la misma convención relativa del módulo 7, equivalente a un lift absoluto de apenas 0.38 puntos porcentuales sobre esa base—, con alpha = 0.05 y power = 0.8. Calcula cuántos usuarios por variante hacen falta.
Ver solución
Con sampleSize({ baseline: 0.038, mde: 0.10, alpha: 0.05, power: 0.8 }): p1 = 0.038, p2 = 0.038 * 1.10 = 0.0418; la varianza exacta es p1*(1-p1) + p2*(1-p2) = 0.038*0.962 + 0.0418*0.9582 ≈ 0.03656 + 0.04005 ≈ 0.07661; (z_alpha/2 + z_beta)² = 2.8² = 7.84; (p2-p1)² = 0.0038² = 0.00001444. n = 7.84 * 0.07661 / 0.00001444 ≈ 41,594 usuarios por variante. Este número —más de tres veces los 12,000 usados en el experimento actual— confirma el mismo patrón de esta lección: aunque 10% relativo parezca un umbral modesto, sigue exigiendo una muestra sustancialmente mayor que el 20% del experimento original, y el equipo tendría que decidir si vale la pena correr el experimento por más tiempo, ampliar la base de usuarios expuestos, o aceptar un MDE menos exigente.
Resumen y siguiente paso
En esta lección calculaste, con sampleSize() y la fórmula estándar de proporciones —la misma, sin aproximar, del módulo 7—, que el experimento de recommendations necesitaba al menos 12,997 usuarios por variante para detectar, con 80% de poder, el MDE pre-registrado de 20% relativo — y confirmaste que la muestra real (12,000 por variante) quedó ligeramente por debajo de ese mínimo, un déficit de 997 usuarios. Con esta cuarta capa del método, ya sabes que cuando la lección 6 confirme si el lift es significativo, ese resultado no viene de un diseño con margen de sobra: viene de un experimento que corrió por debajo de su propio objetivo de muestra, y que salió significativo porque el efecto real resultó ser lo bastante grande — exactamente el margen estrecho que la auditoría del módulo 7 identifica sobre este mismo experimento.
Hacia dónde sigues. La lección 6 junta el protocolo completo del A/B test (control, variant, aleatorización) con el z-test de proporciones que calcula, por fin, si el lift de +18.75% que viste desde la lección 2 (a través del funnel) y la lección 3 (a través de la retención) es un efecto real o ruido de muestreo.
Recursos
- Evan Miller, "Sample Size Calculator" — evanmiller.org/ab-testing/sample-size.html. Una calculadora interactiva basada en la misma fórmula de proporciones de esta lección — útil para verificar el resultado de
sampleSize()con una herramienta independiente. En inglés. - Optimizely, "Sample size calculations for experiments" — optimizely.com/insights/blog/sample-size-calculations-for-experiments. Explica la misma fórmula con foco en cómo elegir el
MDEcorrecto para el negocio, el mismo argumento de la sección "Profundización" de esta lección. En inglés. - Optimizely, "Use minimum detectable effect to prioritize experiments" — support.optimizely.com/hc/en-us/articles/4410283338253. Sobre cómo el
MDEno es solo un parámetro estadístico, sino una decisión de negocio — exactamente el argumento del Ejercicio 2 de esta lección. En inglés.