{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Una prueba A/B de principio a fin\n",
    "\n",
    "El orden en que se hace: primero cuántos hacen falta, después el reparto, y el resultado al final. Y el 17,7% que cuesta mirar antes de tiempo.\n",
    "\n",
    "Cuaderno de soluciones del capítulo 18 de **Estadística desde cero**, de Miss Yera.\n",
    "\n",
    "Corre de arriba abajo. Si lo abres en Google Colab no necesitas instalar nada.\n",
    "\n",
    "Capítulo completo: https://missyera.com/guias/estadistica-desde-cero/una-prueba-ab-de-verdad/\n",
    "\n",
    "Este es el cuaderno de **soluciones**. Trae el código de cada ejercicio, la\n",
    "explicación de la trampa y la respuesta del quiz. Si vienes del cuaderno de\n",
    "práctica sin haberlo intentado, vuelve 🙂"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Diecisiete capítulos de piezas sueltas. Este las monta todas en el orden en\n",
    "que se usan de verdad, sobre la pregunta que más se hace en una empresa:\n",
    "**¿esto que cambiamos sirvió?** 🧪\n",
    "\n",
    "Y te aviso desde ya: lo que hace que una prueba A/B valga o no valga se decide\n",
    "casi todo **antes de empezar**. Cuando ya tienes los datos, lo que\n",
    "queda es una cuenta de tres líneas."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import pandas as pd\n",
    "from scipy import stats\n",
    "\n",
    "URL = 'https://missyera.com/static/datasets/ventas-miss-yera.csv'\n",
    "\n",
    "\n",
    "def carga_limpia(url):\n",
    "    \"\"\"La misma del capítulo 2.\"\"\"\n",
    "    v = pd.read_csv(url).drop_duplicates()\n",
    "    v['ciudad'] = (v['ciudad'].str.strip().str.lower()\n",
    "                   .str.normalize('NFKD')\n",
    "                   .str.encode('ascii', 'ignore').str.decode('utf-8'))\n",
    "    v['monto'] = pd.to_numeric(v['monto'].str.replace(',', '.'))\n",
    "    for col in ['fecha', 'fecha_ultima_compra']:\n",
    "        f = pd.to_datetime(v[col], format='%Y-%m-%d', errors='coerce')\n",
    "        falta = f.isna() & v[col].notna()\n",
    "        f[falta] = pd.to_datetime(v.loc[falta, col], format='%d/%m/%Y',\n",
    "                                  errors='coerce')\n",
    "        v[col] = f\n",
    "    return v\n",
    "\n",
    "\n",
    "v = carga_limpia(URL).dropna(subset=['compro'])\n",
    "BASE = v['compro'].mean()\n",
    "\n",
    "print('clientes: %d' % len(v))\n",
    "print('conversion de hoy: %.4f' % BASE)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ese 0,5777 es el punto de partida, y a partir de él ya se puede contestar la\n",
    "pregunta que casi nadie hace 🐣"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Paso 1, y es el que se salta todo el mundo"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Antes de tocar nada: **¿cuánta gente hace falta para poder ver el cambio\n",
    "que espero?** Si la respuesta es más de la que tienes, el experimento no\n",
    "se hace, porque ya sabes que va a salir \"no concluyente\" pase lo que pase."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def cuantos_hacen_falta(p1, p2, potencia=0.80, alfa=0.05):\n",
    "    \"\"\"Cuantos por grupo para ver un cambio de p1 a p2.\"\"\"\n",
    "    z_a = stats.norm.ppf(1 - alfa / 2)\n",
    "    z_b = stats.norm.ppf(potencia)\n",
    "    p = (p1 + p2) / 2\n",
    "    return int(np.ceil(2 * p * (1 - p) * (z_a + z_b) ** 2 / (p2 - p1) ** 2))\n",
    "\n",
    "\n",
    "print('conversion de hoy: %.4f' % BASE)\n",
    "for mejora in [0.01, 0.02, 0.03, 0.05, 0.10]:\n",
    "    n = cuantos_hacen_falta(BASE, BASE + mejora)\n",
    "    print('  para ver +%.0f puntos: %6d por grupo' % (mejora * 100, n))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ahí está la conversación entera que hay que tener con quien pide el\n",
    "experimento 💼\n",
    "\n",
    "Para ver una mejora de un punto hacen falta **38.172 personas por\n",
    "grupo**, o sea 76.344 en total. Y nosotros tenemos 3.000. Se acabó: ese\n",
    "experimento no se puede hacer aquí, y saberlo hoy vale más que descubrirlo en\n",
    "tres meses.\n",
    "\n",
    "Con 1.500 por grupo solo alcanza para ver cambios de **cinco puntos para\n",
    "arriba**. Así que el experimento solo tiene sentido si de verdad esperas\n",
    "un cambio grande. Fíjate además en la forma de la tabla: bajar de 5 puntos a 1\n",
    "multiplica por veinticinco la gente que necesitas, porque el efecto entra al\n",
    "cuadrado en el denominador. Eso ya salió en el capítulo\n",
    "14, y aquí es lo que decide si hay proyecto o no."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Paso 2, repartir de verdad al azar"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ahora el reparto. Y una cosa que parece de perogrullo y no lo es: se reparte\n",
    "**al azar**, no por ciudad, ni por vendedor, ni por quien conteste\n",
    "primero. Si el reparto no es al azar, lo que midas después mezcla tu cambio con\n",
    "lo que diferencie a los grupos."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "generador = np.random.default_rng(7)\n",
    "lado = generador.permutation(len(v)) % 2\n",
    "v = v.assign(grupo=np.where(lado == 0, 'A', 'B'))\n",
    "\n",
    "print('a cada grupo le tocaron:')\n",
    "print(v['grupo'].value_counts().to_string())\n",
    "print()\n",
    "print('y comprobamos que los grupos salieron parecidos:')\n",
    "print(pd.crosstab(v['grupo'], v['segmento'], normalize='index').round(3).to_string())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Esa segunda tabla es la comprobación de equilibrio, y hay que hacerla siempre\n",
    "📋\n",
    "\n",
    "Los repartos están cerca pero no son idénticos: el grupo B se llevó un 26,1%\n",
    "de mayoristas contra el 23,9% de A. Eso es normal y es el azar haciendo su\n",
    "trabajo. Lo que buscas no es que sean iguales, es que no haya una diferencia\n",
    "gorda que después te explique el resultado.\n",
    "\n",
    "Y esto conecta directo con el capítulo 9: allí\n",
    "el problema era quién entra en la muestra, y aquí es quién cae en cada lado. Es\n",
    "el mismo peligro dos veces."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Paso 3, el resultado"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Hasta aquí no hemos cambiado nada. Los dos grupos reciben exactamente lo mismo,\n",
    "porque quiero enseñarte primero lo que tiene que salir cuando no hay nada:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = v[v['grupo'] == 'A']['compro']\n",
    "b = v[v['grupo'] == 'B']['compro']\n",
    "print('grupo A: %d personas, convierte %.4f' % (len(a), a.mean()))\n",
    "print('grupo B: %d personas, convierte %.4f' % (len(b), b.mean()))\n",
    "print('diferencia: %+.4f' % (b.mean() - a.mean()))\n",
    "\n",
    "tabla = np.array([[a.sum(), len(a) - a.sum()], [b.sum(), len(b) - b.sum()]])\n",
    "print('valor p: %.4f' % stats.chi2_contingency(tabla)[1])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Siete diezmilésimas de diferencia y un valor p de 1,0000 💚\n",
    "\n",
    "Eso es exactamente lo que tenía que salir, porque **no cambiamos\n",
    "nada**. Y esto tiene nombre: es una **prueba A/A**, y es lo\n",
    "primero que se corre antes de cualquier A/B de verdad.\n",
    "\n",
    "Suena a perder el tiempo y es lo contrario. Si tu A/A sale significativa, no\n",
    "has descubierto nada: tienes rota la tubería. El reparto no es al azar, o los\n",
    "grupos se contaminan, o estás contando dos veces al mismo cliente. Correrla\n",
    "cuesta una tarde y te ahorra creerte un hallazgo que era un fallo de plomería 🔧"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Paso 4, y ahora con un cambio de verdad"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Vamos a fabricar un efecto real de cinco puntos y ver si la máquina lo caza:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def experimento(efecto, semilla):\n",
    "    \"\"\"Reparte al azar y le suma `efecto` a la conversion del grupo B.\"\"\"\n",
    "    g = np.random.default_rng(semilla)\n",
    "    lado = g.permutation(len(v)) % 2\n",
    "    base = v['compro'].values.copy()\n",
    "    empujados = (lado == 1) & (base == 0) & (g.random(len(v)) < efecto / (1 - BASE))\n",
    "    base = np.where(empujados, 1, base)\n",
    "    return base[lado == 0], base[lado == 1]\n",
    "\n",
    "\n",
    "a5, b5 = experimento(0.05, 7)\n",
    "print('grupo A convierte %.4f' % a5.mean())\n",
    "print('grupo B convierte %.4f' % b5.mean())\n",
    "t = np.array([[a5.sum(), len(a5) - a5.sum()], [b5.sum(), len(b5) - b5.sum()]])\n",
    "print('valor p: %.6f' % stats.chi2_contingency(t)[1])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Lo caza 🎯\n",
    "\n",
    "Cinco puntos de mejora y un valor p de 0,004. Y no es suerte: la tabla del\n",
    "paso 1 decía que con 1.504 por grupo se ven los cambios de cinco puntos, y\n",
    "tenemos 1.500. El experimento estaba **diseñado** para poder ver\n",
    "esto, y por eso lo ve."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Y ahora el pecado, que es el que de verdad cuesta dinero"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Tienes el experimento corriendo. Van tres días. Y miras. Y al día siguiente\n",
    "miras otra vez. Y el jueves sale p = 0,03 y lo paras y lo anuncias 🎉\n",
    "\n",
    "Vamos a medir cuánto cuesta eso. Trescientos experimentos donde\n",
    "**no hay ningún efecto**, comparando mirar solo al final contra\n",
    "mirar cada cien personas y parar al primer resultado bonito:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def mira_pronto(efecto, semilla, cada=100):\n",
    "    \"\"\"Corre el experimento y va mirando el valor p cada `cada` personas.\"\"\"\n",
    "    a, b = experimento(efecto, semilla)\n",
    "    for n in range(cada, len(a) + 1, cada):\n",
    "        ta = np.array([[a[:n].sum(), n - a[:n].sum()],\n",
    "                       [b[:n].sum(), n - b[:n].sum()]])\n",
    "        if ta.min() == 0:\n",
    "            continue\n",
    "        if stats.chi2_contingency(ta)[1] < 0.05:\n",
    "            return True\n",
    "    return False\n",
    "\n",
    "\n",
    "sin_efecto = sum(mira_pronto(0.0, s) for s in range(300))\n",
    "print('de 300 experimentos donde NO hay ningun efecto real:')\n",
    "print('  mirando solo al final, lo esperado es el 5.0%')\n",
    "print('  mirando cada 100 personas y parando al primer p<0.05: %.1f%%'\n",
    "      % (sin_efecto / 300 * 100))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Del 5% al 17,7% 😱\n",
    "\n",
    "Uno de cada seis experimentos **sin ningún efecto** te va a dar un\n",
    "resultado significativo en algún momento del camino, si te dedicas a mirar. Y lo\n",
    "vas a parar justo ahí, porque es cuando la noticia es buena.\n",
    "\n",
    "No hace falta mala fe. Basta con querer saber cómo va. El valor p del capítulo\n",
    "12 promete un 5% de falsas alarmas **si miras una\n",
    "vez**, y cada vistazo extra es una oportunidad más de que el azar te\n",
    "sonría."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "El tamaño de la muestra y la fecha de parada se escriben antes de empezar. Todo lo que se decida después de ver los datos ya no es un experimento."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Los dos errores, y el peor es el que no revienta"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Empiezo por el que sí revienta, y es bonito porque la que se queja es la\n",
    "aritmética:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Esto revienta a propósito.** Se ejecuta dentro de un `try` para que puedas seguir con \"ejecutar todo\" y aun así ver la queja."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "try:\n",
    "    cuantos_hacen_falta(BASE, BASE)\n",
    "except Exception as e:\n",
    "    print(f'{type(e).__name__}: {e}')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Y la queja que tiene que salir es esta:\n",
    "\n",
    "```\n",
    "OverflowError: cannot convert float infinity to integer\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Le preguntaste cuánta gente hace falta para detectar una mejora de cero, y la\n",
    "respuesta es **infinita**. Tiene todo el sentido: una diferencia que\n",
    "no existe no se detecta nunca, por mucha gente que metas. La división entre cero\n",
    "del denominador es esa frase escrita en números 🔑\n",
    "\n",
    "Y ahora el que no revienta, que es el que te va a morder de verdad.\n",
    "`chi2_contingency` quiere **cuántos**, no **qué\n",
    "proporción**. Si le pasas las tasas de conversión en vez de los conteos:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "stats.chi2_contingency(np.array([[0.5780, 0.4220],\n",
    "                                 [0.6300, 0.3700]]))\n",
    "# devuelve p = 1.0000, sin una sola queja\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Un valor p perfectamente formado, perfectamente inútil y perfectamente\n",
    "silencioso. Con proporciones la prueba cree que tienes **un cliente por\n",
    "grupo** en vez de mil quinientos, así que no encuentra nada nunca.\n",
    "\n",
    "La comprobación cabe en una línea y hay que hacerla siempre:\n",
    "`tabla.sum()` tiene que darte el número de personas del experimento.\n",
    "Si te da 2, la tabla está en proporciones 🚩"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## La receta entera, para tenerla a mano"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "| Cuándo | Qué se hace | Qué pasa si te lo saltas |\n",
    "|---|---|---|\n",
    "| **Antes** | Escribir la pregunta y qué mejora valdría la pena | Al final se elige la métrica que salió bien |\n",
    "| **Antes** | Calcular cuántos hacen falta, y cancelar si no los tienes | Tres meses para un \"no concluyente\" que ya se sabía |\n",
    "| **Antes** | Fijar la fecha de parada | El 17,7% de arriba |\n",
    "| **Al empezar** | Repartir al azar y correr una A/A | Se confunde el cambio con lo que ya diferenciaba a los grupos |\n",
    "| **Al empezar** | Comprobar que los grupos quedaron parecidos | Un desequilibrio gordo explica el resultado y nadie lo mira |\n",
    "| **Al final** | Una prueba, un intervalo y el tamaño del efecto | Se reporta un valor p solo, que no dice si importa |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Cuatro de las seis filas son de antes de empezar, y eso es lo que quiero que\n",
    "te lleves de este capítulo 🗓️\n",
    "\n",
    "Si quieres leer más, la guía de experimentos de\n",
    "[exp-platform](https://exp-platform.com/), que es el equipo que montó la\n",
    "experimentación en Microsoft, tiene los casos reales de todo lo que sale mal, y\n",
    "son mucho más raros de lo que uno se imagina 📄"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### La trampa\n",
    "\n",
    "Una tienda prueba un botón nuevo. A la semana el equipo reporta que el grupo B convierte más y que el valor p es 0,012, y lo lanzan a todos.\n",
    "\n",
    "```\n",
    "# lunes\n",
    "print(prueba(a[:400], b[:400]))     # p = 0.31, seguimos\n",
    "# miercoles\n",
    "print(prueba(a[:900], b[:900]))     # p = 0.18, seguimos\n",
    "# viernes\n",
    "print(prueba(a[:1500], b[:1500]))   # p = 0.012  y lo paramos aqui\n",
    "```\n",
    "\n",
    "**Qué está mal**\n",
    "\n",
    "Miraron tres veces y pararon en la que salió bien. Eso ya no es una prueba con un 5% de falsas alarmas: en el capítulo está medido que mirando cada cien personas y parando al primer `p` bonito, el 17,7% de los experimentos **sin ningún efecto** acaban dando significativo. Y fíjate en lo que hace de esto una trampa y no un error: cada una de las tres líneas es correcta por separado. La prueba está bien hecha, los datos son buenos y el 0,012 es de verdad. Lo que está mal es que la decisión de parar dependió del resultado. Se arregla de dos formas, y las dos hay que tomarlas antes: fijar la fecha de parada y no moverla, o usar una prueba diseñada para mirar varias veces, que existen y se llaman secuenciales."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Ejercicios"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Seis. El 2 es el que te va a servir mañana en una reunión 💛"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1. Corre tu propia A/A\n",
    "\n",
    "Reparte al azar veinte veces sin cambiar nada y cuenta\n",
    "cuántas salen significativas."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "salen = 0\n",
    "for s in range(20):\n",
    "    a0, b0 = experimento(0.0, s)\n",
    "    t0 = np.array([[a0.sum(), len(a0) - a0.sum()], [b0.sum(), len(b0) - b0.sum()]])\n",
    "    salen += stats.chi2_contingency(t0)[1] < 0.05\n",
    "print('significativas de 20:', salen)\n",
    "Tiene que salir cerca de una. Si te salen cinco, el problema está en cómo\n",
    "repartes y no en el mundo."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. La calculadora de antes de empezar\n",
    "\n",
    "Con la conversión de tu negocio, haz la tabla de cuánta\n",
    "gente necesitas para cada mejora."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "for base in [0.02, 0.10, 0.30, 0.58]:\n",
    "    fila = [cuantos_hacen_falta(base, base + d) for d in (0.01, 0.02, 0.05)]\n",
    "    print('conversion %.2f -> +1pt: %7d   +2pt: %7d   +5pt: %6d' % (base, *fila))\n",
    "Guárdate esa tabla. Es lo que hay que enseñar cuando alguien propone un\n",
    "experimento, y suele terminar la conversación en dos minutos."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3. Cuánto cuesta mirar más seguido\n",
    "\n",
    "Repite la medición del 17,7% mirando cada 50, cada 100 y\n",
    "cada 300 personas."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Cuanto más seguido miras, peor. Y la pregunta buena del ejercicio: si mirar\n",
    "cada cien te da 17,7% y mirar una sola vez te da 5%, ¿qué pasa con un panel que\n",
    "enseña el valor p en tiempo real a todo el mundo? 📊"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4. Ponle intervalo a la diferencia\n",
    "\n",
    "Con el bootstrap del capítulo\n",
    "11, dale un intervalo a la diferencia entre A y B."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Un valor p te dice si crees que hay algo. El intervalo te dice cuánto, y es lo\n",
    "que hace falta para decidir si el cambio paga. Reportar los dos es lo que separa\n",
    "un informe de un titular."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 5. El efecto que no alcanzas a ver\n",
    "\n",
    "Fabrica un efecto real de dos puntos y mira si la prueba lo\n",
    "detecta."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "No lo va a detectar casi nunca, y no porque el efecto no exista: la tabla del\n",
    "paso 1 dice que para dos puntos hacen falta 9.510 por grupo y tenemos 1.500.\n",
    "Ojo con lo que eso significa de verdad, que es la lección escondida: un \"no\n",
    "significativo\" en un experimento pequeño **no es evidencia de que no\n",
    "funcione**."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 6. Mira si el efecto es igual en todos los segmentos\n",
    "\n",
    "Parte el resultado por `segmento` y mira si el\n",
    "cambio ayuda a todos por igual."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Cuidado con este, que es el más peligroso de los seis. Partir por segmentos\n",
    "después de ver el resultado es exactamente el p-hacking del capítulo\n",
    "17: con cuatro segmentos tienes cuatro oportunidades\n",
    "de encontrar algo. Se hace, y se reporta diciendo que se hizo después y que hay\n",
    "que confirmarlo con otro experimento 🚩"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 7. Lo que cuestan la potencia y el alfa\n",
    "\n",
    "Deja fijos los tres puntos de mejora y mueve la potencia y el alfa. Arma la tabla del precio de cada combinación."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "print('%-9s %10s %10s %10s' % ('potencia', 'alfa 0.10', 'alfa 0.05', 'alfa 0.01'))\n",
    "for potencia in [0.50, 0.80, 0.90, 0.95]:\n",
    "    fila = [cuantos_hacen_falta(BASE, BASE + 0.03, potencia, a)\n",
    "            for a in (0.10, 0.05, 0.01)]\n",
    "    print('%-9.2f %10d %10d %10d' % (potencia, fila[0], fila[1], fila[2]))\n",
    "potencia   alfa 0.10  alfa 0.05  alfa 0.01\n",
    "0.50            1452       2061       3560\n",
    "0.80            3317       4211       6266\n",
    "0.90            4595       5637       7983\n",
    "0.95            5806       6972       9557\n",
    "La misma mejora cuesta 1452 personas o cuesta 9557 😵\n",
    "\n",
    "Es un factor de seis y medio, y lo único que cambió son dos números que casi nadie discute porque vienen puestos. La fila de potencia 0,50 es la más honesta de todas: con esa muestra, si la mejora existe, la ves la mitad de las veces. Es tirar una moneda.\n",
    "\n",
    "**Cuando alguien te diga que no hay presupuesto para tantos usuarios, enséñale esta tabla y que escoja la fila.** No es lo mismo recortar la muestra que recortar las ganas de enterarte 💰"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 8. La potencia, comprobada a mano\n",
    "\n",
    "Corre el experimento doscientas veces con tres efectos distintos y cuenta cuántas veces sale significativo."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "def sale_significativo(efecto, semilla):\n",
    "    a, b = experimento(efecto, semilla)\n",
    "    t = np.array([[a.sum(), len(a) - a.sum()],\n",
    "                  [b.sum(), len(b) - b.sum()]])\n",
    "    return stats.chi2_contingency(t)[1] < 0.05\n",
    "\n",
    "for efecto in [0.00, 0.02, 0.05]:\n",
    "    salen = sum(sale_significativo(efecto, s) for s in range(200))\n",
    "    print('con un efecto de %.2f sale significativo %3d de 200 veces (%.1f%%)'\n",
    "          % (efecto, salen, salen / 2))\n",
    "con un efecto de 0.00 sale significativo   5 de 200 veces (2.5%)\n",
    "con un efecto de 0.02 sale significativo  38 de 200 veces (19.0%)\n",
    "con un efecto de 0.05 sale significativo 163 de 200 veces (81.5%)\n",
    "Este ejercicio comprueba la fórmula del capítulo con la fuerza bruta 🔬\n",
    "\n",
    "La cuenta pedía 1504 por grupo para ver cinco puntos con potencia 0,80, y aquí cada grupo tiene unos 1500. Sale 81,5 por ciento de las veces. La fórmula no era un adorno.\n",
    "\n",
    "Las otras dos filas valen igual. Sin efecto ninguno salta el 2,5 por ciento de las veces, que es el falso positivo del que habla 17. Y con dos puntos de mejora real, que es una mejora que cualquiera firmaría, **este experimento la encuentra 19 veces de cada 100 y la deja pasar las otras 81**. Ahí es donde mueren los tests que \"no dieron nada\" 🪦"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Comprueba que lo tienes\n",
    "\n",
    "Tu experimento lleva cuatro días de los diez planeados y ya sale p = 0,04. ¿Qué haces?\n",
    "\n",
    "a) Lo dejas correr hasta el día diez, como estaba escrito\n",
    "\n",
    "b) Lo paras y lo lanzas, que ya salió\n",
    "\n",
    "c) Lo paras y corres otro para confirmar\n",
    "\n",
    "d) Sigues y a partir de ahora miras todos los días\n",
    "\n",
    "---\n",
    "\n",
    "**La correcta es la a.**\n",
    "\n",
    "*b)* Eso es justo lo que sube los falsos hallazgos del 5% al 17,7%. Y el que para es siempre el que salió bien, nunca el que salió mal.\n",
    "\n",
    "*c)* Mejor que lanzarlo, y sigues perdiendo la mitad del experimento que ya estabas pagando. Déjalo terminar y tendrás las dos cosas.\n",
    "\n",
    "*d)* Dejarlo correr está bien. Mirarlo cada día es lo que hay que evitar, porque tarde o temprano vas a querer parar.\n",
    "\n",
    "La fecha de parada es parte del diseño. Cambiarla al ver los datos convierte el experimento en una búsqueda."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Lo que te llevas"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 🗓️ Cuatro de los seis pasos son antes de empezar. Lo de después son tres\n",
    "líneas.\n",
    "\n",
    "- 🔢 Para ver +1 punto sobre una conversión de 0,5777 hacen falta 38.172 por\n",
    "grupo. Con 3.000 clientes ese experimento no se puede hacer, y saberlo hoy vale\n",
    "más que descubrirlo en tres meses.\n",
    "\n",
    "- 🔁 La prueba A/A va primero: si sale significativa sin cambiar nada, lo roto\n",
    "es la tubería.\n",
    "\n",
    "- 👀 Mirar cada cien personas y parar en el primer resultado bonito sube los\n",
    "falsos hallazgos del 5% al 17,7%.\n",
    "\n",
    "- 📉 Y un \"no significativo\" con muestra chica no dice que el cambio no\n",
    "sirva.\n",
    "\n",
    "El capítulo 19 hace este mismo recorrido sobre una\n",
    "pregunta de negocio entera y termina en un informe de una página. Y el\n",
    "vocabulario suelto está en el [glosario de IA](https://missyera.com/glosario-ia/) 📖\n",
    "\n",
    "Que tengas lindo día! 🌸"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "Ese era el capítulo 18 de **Estadística desde cero**. El texto completo, con las salidas de cada bloque, está en https://missyera.com/guias/estadistica-desde-cero/una-prueba-ab-de-verdad/\n",
    "\n",
    "Que tengas lindo día! 🌸"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python",
   "version": "3.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
