{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# La prueba de hipótesis y el valor p\n",
    "\n",
    "Calculado a mano barajando etiquetas, para que veas exactamente qué es antes de que ninguna fórmula te lo esconda.\n",
    "\n",
    "Cuaderno de soluciones del capítulo 12 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/prueba-de-hipotesis/\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": [
    "Llegamos al número más famoso y peor entendido de la estadística: el\n",
    "**valor p** 🏆\n",
    "\n",
    "Y te lo voy a enseñar de una forma que casi nadie usa: **calculándolo a\n",
    "mano**, barajando cartas. Cuando lo veas así, ya no se te va a olvidar\n",
    "nunca, y las fórmulas de después van a ser un atajo y no una caja negra.\n",
    "\n",
    "Y contéstate una, aunque sea a ojo: **¿qué crees que significa exactamente \"p menor que 0,05\"?** Guarda tu respuesta y compárala al final. Casi nadie acierta la primera vez, y yo tampoco acerté 🎓"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## La pregunta, en su forma más honesta"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "En el capítulo 10 encontramos esto: Horeca cierra el 63,21% de sus ventas y\n",
    "Minimarket el 56,93%. Una diferencia de 6,28 puntos.\n",
    "\n",
    "La pregunta es la de siempre: **¿eso es real o es ruido?**\n",
    "\n",
    "Y la forma de contestarla es preciosa. Consiste en *suponer que no hay\n",
    "ninguna diferencia* y ver qué tan raro sería, en ese mundo, encontrar los\n",
    "6,28 puntos que encontramos.\n",
    "\n",
    "A esa suposición se le llama **hipótesis nula**. Es el abogado\n",
    "del diablo: parte de que no pasa nada, y le toca a tus datos convencerla de lo\n",
    "contrario 👩‍⚖️"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\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)\n",
    "\n",
    "horeca = v.loc[v['segmento'] == 'Horeca', 'compro'].values\n",
    "minimarket = v.loc[v['segmento'] == 'Minimarket', 'compro'].values\n",
    "observada = horeca.mean() - minimarket.mean()\n",
    "\n",
    "print('Horeca:     %.4f (%d ventas)' % (horeca.mean(), len(horeca)))\n",
    "print('Minimarket: %.4f (%d ventas)' % (minimarket.mean(), len(minimarket)))\n",
    "print('diferencia: %.6f' % observada)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Barajando las etiquetas"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Aquí viene lo bonito 🃏\n",
    "\n",
    "Si la hipótesis nula fuera cierta, o sea si el segmento no influyera en nada,\n",
    "entonces las etiquetas \"Horeca\" y \"Minimarket\" estarían puestas\n",
    "**al azar** sobre esas 1.543 ventas.\n",
    "\n",
    "Así que vamos a hacer justo eso: mezclar las etiquetas mil veces y ver qué\n",
    "diferencias salen en un mundo donde no pasa nada."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "generador = np.random.default_rng(7)\n",
    "todas = np.concatenate([horeca, minimarket])\n",
    "n_horeca = len(horeca)\n",
    "\n",
    "diferencias = []\n",
    "for _ in range(10000):\n",
    "    generador.shuffle(todas)\n",
    "    diferencias.append(todas[:n_horeca].mean() - todas[n_horeca:].mean())\n",
    "\n",
    "diferencias = np.array(diferencias)\n",
    "\n",
    "print('diferencias al azar: media %+.6f | desviacion %.6f'\n",
    "      % (diferencias.mean(), diferencias.std()))\n",
    "print('la mayor que salio por azar: %.6f' % np.abs(diferencias).max())\n",
    "print('la nuestra:                  %.6f' % abs(observada))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Fíjate en lo que acabamos de fabricar: **el mundo donde no pasa\n",
    "nada**. En ese mundo las diferencias entre los dos grupos se mueven\n",
    "alrededor de cero con una desviación de 0,025 🌍\n",
    "\n",
    "Y ahora el valor p, que es literalmente *contar*:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "p = np.mean(np.abs(diferencias) >= abs(observada))\n",
    "\n",
    "print('de 10000 mundos sin efecto, cuantos dieron una diferencia asi de grande o mas:')\n",
    "print('   %d' % (np.abs(diferencias) >= abs(observada)).sum())\n",
    "print('valor p = %.4f' % p)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Ese es el valor p. Y ya está.** 🎉\n",
    "\n",
    "Se lee así: *si el segmento no influyera en nada, solo el 1,55% de las\n",
    "veces vería una diferencia tan grande como la que vi*.\n",
    "\n",
    "No hay más misterio. Un valor p es la proporción de mundos-sin-efecto que\n",
    "producen algo tan llamativo como lo tuyo."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Y ahora la fórmula, que es el atajo"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Lo que acabamos de hacer se llama prueba de permutación y tarda unos\n",
    "segundos. La prueba t hace lo mismo con una fórmula, en una línea:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "t=x¯1−x¯2s12n1+s22n2\n",
    "\n",
    "la diferencia entre los dos grupos medida en errores estándar, o sea cuántas veces cabe el ruido dentro de lo que encontraste"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "resultado = stats.ttest_ind(horeca, minimarket, equal_var=False)\n",
    "\n",
    "print('permutacion (barajando): p = %.4f' % p)\n",
    "print('prueba t (formula):      p = %.4f' % resultado.pvalue)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "0,0155 y 0,0118. Prácticamente lo mismo 🤝\n",
    "\n",
    "La fórmula supone que las diferencias al azar siguen una campana, y por eso\n",
    "va más rápido. La permutación no supone nada: se fabrica el mundo sin efecto de\n",
    "verdad. Cuando las dos coinciden, como aquí, es que la suposición de la fórmula\n",
    "era razonable.\n",
    "\n",
    "Yo uso la fórmula por comodidad y la permutación cuando el resultado es\n",
    "importante o los datos son raros. Y las dos veces sé lo que estoy calculando,\n",
    "que es de lo que iba este capítulo 😌"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## El contraste: cuando de verdad no hay nada"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Hagamos lo mismo con dos ciudades, que llevamos nueve capítulos viendo que no\n",
    "separan nada:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "trujillo = v.loc[v['ciudad'] == 'trujillo', 'compro'].values\n",
    "piura = v.loc[v['ciudad'] == 'piura', 'compro'].values\n",
    "\n",
    "print('trujillo %.4f | piura %.4f | diferencia %.4f'\n",
    "      % (trujillo.mean(), piura.mean(), trujillo.mean() - piura.mean()))\n",
    "print('prueba t: p = %.4f'\n",
    "      % stats.ttest_ind(trujillo, piura, equal_var=False).pvalue)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "p = 0,4634. O sea que **casi la mitad de los mundos sin efecto\n",
    "producirían una diferencia así** 🤷\n",
    "\n",
    "Y ojo con cómo se dice esto, porque es donde se resbala todo el mundo. No se\n",
    "dice \"queda demostrado que las ciudades cierran igual\". Se dice **\"no\n",
    "tengo evidencia de que sean distintas\"**.\n",
    "\n",
    "La diferencia importa: puede que Trujillo cierre mejor de verdad y que 471\n",
    "ventas no alcancen para verlo. **Ausencia de evidencia no es evidencia de\n",
    "ausencia** 🕵️"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## El 0,05, que no tiene nada de mágico"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Se corta en 0,05 por costumbre. Lo propuso Ronald Fisher en los años veinte\n",
    "como una guía razonable y se quedó para siempre.\n",
    "\n",
    "Lo que sí es concreto es **qué te cuesta** ese corte. Vamos a\n",
    "verlo con datos donde sabemos que no hay ningún efecto porque los fabrico yo:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "falsos = 0\n",
    "for _ in range(1000):\n",
    "    a = generador.normal(size=50)\n",
    "    b = generador.normal(size=50)\n",
    "    if stats.ttest_ind(a, b).pvalue < 0.05:\n",
    "        falsos += 1\n",
    "\n",
    "print('comparaciones sin ningun efecto: 1000')\n",
    "print('salieron significativas:         %d' % falsos)\n",
    "print('o sea el %.1f%%' % (falsos / 10))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "El 5,7%, o sea el 5% prometido 🎯\n",
    "\n",
    "Eso es lo que significa alfa = 0,05: **estás aceptando equivocarte una\n",
    "de cada veinte veces cuando no hay nada**. No es un defecto, es el precio\n",
    "que eliges pagar.\n",
    "\n",
    "Y de ahí sale la tabla de los dos errores, que conviene tener clara:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "|  | No hay efecto | Sí hay efecto |\n",
    "|---|---|---|\n",
    "| **Dices que sí hay** | Error tipo I (falsa alarma), pasa el 5% | Correcto 🎉 |\n",
    "| **Dices que no hay** | Correcto | Error tipo II (te lo perdiste) |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Bajar alfa a 0,01 reduce las falsas alarmas y aumenta las veces que te pierdes\n",
    "algo real. No hay forma de reducir los dos a la vez sin conseguir más datos. Eso\n",
    "es el capítulo 14 💪"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Las cuatro cosas que un valor p NO dice"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Esta lista vale el capítulo entero. Cada una la he oído en una reunión 🙃\n",
    "\n",
    "- ❌ **\"p = 0,0155 quiere decir que hay 98,45% de probabilidad de que la\n",
    "diferencia sea real.\"** No. El p se calcula *suponiendo* que no hay\n",
    "diferencia; no puede decirte la probabilidad de que la haya.\n",
    "\n",
    "- ❌ **\"p = 0,0155 quiere decir que hay 1,55% de probabilidad de que sea\n",
    "casualidad.\"** Tampoco, y es la más común. Es la probabilidad de ver\n",
    "*estos datos* si fuera casualidad, que es al revés. Es el mismo error de\n",
    "dar la vuelta a una condicional del capítulo 7.\n",
    "\n",
    "- ❌ **\"p chiquito quiere decir efecto grande.\"** No. El p mezcla\n",
    "tamaño del efecto y cantidad de datos. Con muchísimas filas, un efecto ridículo\n",
    "sale con p diminuto.\n",
    "\n",
    "- ❌ **\"p = 0,06 quiere decir que no hay nada.\"** No. 0,049 y\n",
    "0,051 son prácticamente el mismo resultado, y el corte en 0,05 es una\n",
    "convención.\n",
    "\n",
    "Si te llevas una sola frase del capítulo, que sea esta:\n",
    "**significativo no quiere decir importante** 📌"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## El error del capítulo"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Quiero comparar la satisfacción entre dos segmentos:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sa = v.loc[v['segmento'] == 'Horeca', 'satisfaccion']\n",
    "sb = v.loc[v['segmento'] == 'Bodega', 'satisfaccion']\n",
    "\n",
    "print(stats.ttest_ind(sa, sb))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`nan` por todas partes, sin error y sin aviso 🫥\n",
    "\n",
    "La causa son los 231 nulos de `satisfaccion`. Cualquier cuenta que\n",
    "toque un `nan` devuelve `nan`, y como el resultado\n",
    "*parece* un resultado, se puede copiar a una diapositiva tal cual.\n",
    "\n",
    "Un p de `nan` no es \"no significativo\": es \"no calculé nada\"."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(stats.ttest_ind(sa, sb, nan_policy='omit'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ahora sí: p = 0,3419, o sea que la satisfacción no distingue esos dos\n",
    "segmentos. Que es lo que ya sospechábamos desde el capítulo 3.\n",
    "\n",
    "Y el error que sí te frena, por si te lo preguntas:"
   ]
  },
  {
   "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",
    "    stats.ttest_ind(sa.dropna(), sb.dropna(), alternative='mayor')\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",
    "ValueError: `alternative` must be 'less', 'greater', or 'two-sided'.\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ese está en inglés y hay que escribirlo `greater`. Lo pongo porque\n",
    "la comparación es justa: **el parámetro mal escrito te para, y los datos\n",
    "mal preparados no** 😤"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Y dos más, el primero de los que más se repiten"
   ]
  },
  {
   "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",
    "    stats.ttest_ind(horeca, minimarket, alternative='mayor')\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",
    "ValueError: `alternative` must be 'less', 'greater', or 'two-sided'.\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Las opciones van en inglés y son esas tres. Y lo importante no es la palabra: es que **elegir una cola en vez de dos es una decisión estadística**, no de escritura. Con una cola encuentras significativo más fácil, así que se decide antes de mirar los datos o no vale."
   ]
  },
  {
   "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",
    "    stats.ttest_ind(horeca)\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",
    "TypeError: ttest_ind() missing 1 required positional argument: 'b'\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Una prueba de dos muestras necesita dos muestras. Sale cuando uno tiene los grupos en una tabla y se olvida de partirla, y el mensaje es de los claros: falta `b`."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Practica 💪"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1. Prueba tú la diferencia grande\n",
    "\n",
    "Compara Mayorista contra Bodega, que son los dos extremos.\n",
    "¿Qué valor p sale?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "may = v.loc[v['segmento'] == 'Mayorista', 'compro'].values\n",
    "bod = v.loc[v['segmento'] == 'Bodega', 'compro'].values\n",
    "\n",
    "r = stats.ttest_ind(may, bod, equal_var=False)\n",
    "print('mayorista %.4f | bodega %.4f | diferencia %.4f'\n",
    "      % (may.mean(), bod.mean(), may.mean() - bod.mean()))\n",
    "print('t = %.4f' % r.statistic)\n",
    "print('p = %.3e' % r.pvalue)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "mayorista 0.7240 | bodega 0.3748 | diferencia 0.3492\n",
    "t = 14.2705\n",
    "p = 2.726e-43\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "p = 2,7 por 10 elevado a -43. O sea un cero, una coma y cuarenta y dos ceros\n",
    "más antes del primer dígito 😅\n",
    "\n",
    "Cuando un valor p sale así de chico, ya no aporta nada leerlo como\n",
    "probabilidad. Lo único que dice es \"esto no es casualidad, ni de lejos\".\n",
    "\n",
    "Y aquí es donde hay que cambiar de pregunta. Ya sabemos que la diferencia es\n",
    "real; lo que hay que reportar es **cuánto**: 34,92 puntos de\n",
    "diferencia en la tasa de cierre. Ese número sí sirve para decidir algo.\n",
    "\n",
    "Reportar \"p menor que 0,001\" y quedarse ahí es de las cosas que más frenan\n",
    "una reunión 🛑"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. El mismo efecto con menos datos\n",
    "\n",
    "Coge la diferencia de Horeca contra Minimarket, que salió\n",
    "con p = 0,0118, y repítela usando solo 100 ventas de cada uno."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "for tamano in [100, 200, 400, 742]:\n",
    "    a = generador.choice(horeca, min(tamano, len(horeca)), replace=False)\n",
    "    b = generador.choice(minimarket, min(tamano, len(minimarket)), replace=False)\n",
    "    r = stats.ttest_ind(a, b, equal_var=False)\n",
    "    print('con %3d de cada uno -> diferencia %+.4f | p = %.4f'\n",
    "          % (tamano, a.mean() - b.mean(), r.pvalue))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "con 100 de cada uno -> diferencia +0.0000 | p = 1.0000\n",
    "con 200 de cada uno -> diferencia +0.1050 | p = 0.0339\n",
    "con 400 de cada uno -> diferencia +0.0650 | p = 0.0610\n",
    "con 742 de cada uno -> diferencia +0.0580 | p = 0.0225\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Mira qué inestable 😬\n",
    "\n",
    "El mismo efecto que con toda la muestra daba 0,0118 aquí sale 1,0000, 0,0339,\n",
    "0,0610 y 0,0225 según con cuántas filas y cuáles te toque.\n",
    "\n",
    "Y fíjate en el detalle más incómodo, el primero: con 100 de cada uno la\n",
    "diferencia observada fue **exactamente cero**, y el p salió 1,0000.\n",
    "Con esa muestra habrías concluido que los dos segmentos cierran igual, y te\n",
    "habrías equivocado.\n",
    "\n",
    "Mira también el tercero: 400 de cada uno, diferencia +0,0650 (más grande que\n",
    "la real) y p = 0,0610, o sea justo por encima del corte. Ahí habrías dicho \"no\n",
    "hay nada\" teniendo el efecto delante.\n",
    "\n",
    "Esto es lo que hay detrás de la mitad de los estudios que no se replican.\n",
    "**Con muestras chicas, el valor p es casi un sorteo** 🎰"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3. La prueba de una sola muestra\n",
    "\n",
    "¿El monto promedio de este archivo es distinto de 800\n",
    "soles? Es la otra prueba clásica: comparar contra un número fijo."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "for referencia in [800, 750, 803]:\n",
    "    r = stats.ttest_1samp(v['monto'], referencia)\n",
    "    print('contra %d soles -> t = %+7.4f | p = %.4f' % (referencia, r.statistic, r.pvalue))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "contra 800 soles -> t = +0.2740 | p = 0.7841\n",
    "contra 750 soles -> t = +3.9158 | p = 0.0001\n",
    "contra 803 soles -> t = +0.0554 | p = 0.9558\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Contra 800 el p es 0,7841: no puedo afirmar que el promedio sea distinto de\n",
    "800. Contra 750 el p es 0,0001: sí puedo 📊\n",
    "\n",
    "Y date cuenta de lo que esto es en realidad: **la misma información que\n",
    "el intervalo de confianza del capítulo 10**, que iba de 776,84 a 830,68.\n",
    "\n",
    "800 está dentro del intervalo, así que no se rechaza. 750 está fuera, así que\n",
    "se rechaza. **Toda prueba de hipótesis se puede leer como \"¿está este\n",
    "número dentro del intervalo?\"**, y esa forma me gusta más porque de paso\n",
    "te dice el tamaño 💚"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4. Cuando la fórmula y la permutación no coinciden\n",
    "\n",
    "Compara el monto (no la tasa de compra) entre Horeca y\n",
    "Minimarket con las dos formas. Los montos tienen cola, a ver si aguanta."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "ma = v.loc[v['segmento'] == 'Horeca', 'monto'].values\n",
    "mb = v.loc[v['segmento'] == 'Minimarket', 'monto'].values\n",
    "obs = ma.mean() - mb.mean()\n",
    "\n",
    "juntos = np.concatenate([ma, mb])\n",
    "difs = []\n",
    "for _ in range(10000):\n",
    "    generador.shuffle(juntos)\n",
    "    difs.append(juntos[:len(ma)].mean() - juntos[len(ma):].mean())\n",
    "difs = np.array(difs)\n",
    "\n",
    "print('diferencia observada: %.2f soles' % obs)\n",
    "print('permutacion: p = %.4f' % np.mean(np.abs(difs) >= abs(obs)))\n",
    "print('prueba t:    p = %.3e' % stats.ttest_ind(ma, mb, equal_var=False).pvalue)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "diferencia observada: 340.26 soles\n",
    "permutacion: p = 0.0000\n",
    "prueba t:    p = 2.535e-143\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Las dos dicen lo mismo: imposible que sea casualidad 🎯\n",
    "\n",
    "La permutación dice 0,0000 porque de 10.000 mundos sin efecto,\n",
    "**ninguno** produjo una diferencia de 340 soles. Ese es su límite:\n",
    "no puede darte un p más chico que 1 entre 10.000.\n",
    "\n",
    "La fórmula sí puede, y dice 2,5 por 10 elevado a -143. Ese número no significa\n",
    "nada práctico, pero muestra bien la diferencia entre las dos herramientas:\n",
    "**la permutación es honesta hasta donde llega, la fórmula extrapola**.\n",
    "\n",
    "Cuando necesites un p de verdad chiquito, la fórmula. Cuando necesites no\n",
    "suponer nada, barajar 🃏"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 5. Fabrica un falso positivo\n",
    "\n",
    "Añade cinco columnas de basura al azar y prueba cada una\n",
    "contra `compro`. ¿Alguna sale significativa?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "for i in range(5):\n",
    "    basura = generador.normal(size=len(v))\n",
    "    grupo_a = basura[v['compro'] == 1]\n",
    "    grupo_b = basura[v['compro'] == 0]\n",
    "    r = stats.ttest_ind(grupo_a, grupo_b)\n",
    "    marca = '  <-- SIGNIFICATIVA' if r.pvalue < 0.05 else ''\n",
    "    print('columna de basura %d -> p = %.4f%s' % (i + 1, r.pvalue, marca))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "columna de basura 1 -> p = 0.0700\n",
    "columna de basura 2 -> p = 0.5952\n",
    "columna de basura 3 -> p = 0.9215\n",
    "columna de basura 4 -> p = 0.1748\n",
    "columna de basura 5 -> p = 0.1566\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Esta vez ninguna, y tiene sentido: con cinco pruebas al 5%, la probabilidad de\n",
    "que salte alguna es del 22,6% 🎲\n",
    "\n",
    "Prueba a subir el número a 50 y verás salir dos o tres. Son columnas de ruido\n",
    "puro, generadas por mí, sin ninguna relación posible con la compra. Y aun así\n",
    "algunas van a \"salir significativas\".\n",
    "\n",
    "Eso es exactamente lo que pasa cuando alguien cruza treinta variables buscando\n",
    "\"qué influye en las ventas\". Encuentra cosas. Y algunas son esto 🗑️\n",
    "\n",
    "Tiene nombre, se llama comparaciones múltiples, y tiene su sección en el\n",
    "capítulo 17."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 6. La prueba que no supone nada de la forma\n",
    "\n",
    "La prueba t compara medias y supone campana. Prueba la\n",
    "alternativa que compara posiciones sin suponer forma: Mann-Whitney."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print('comparando montos de Horeca contra Minimarket')\n",
    "print('  medias:   %.2f contra %.2f' % (ma.mean(), mb.mean()))\n",
    "print('  medianas: %.2f contra %.2f' % (np.median(ma), np.median(mb)))\n",
    "print()\n",
    "print('prueba t (medias):        p = %.3e'\n",
    "      % stats.ttest_ind(ma, mb, equal_var=False).pvalue)\n",
    "print('Mann-Whitney (posicion):  p = %.3e'\n",
    "      % stats.mannwhitneyu(ma, mb).pvalue)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "comparando montos de Horeca contra Minimarket\n",
    "  medias:   755.18 contra 414.92\n",
    "  medianas: 743.00 contra 413.74\n",
    "\n",
    "prueba t (medias):        p = 2.535e-143\n",
    "Mann-Whitney (posicion):  p = 1.022e-142\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Las dos dicen que sí, y con una contundencia casi idéntica: 10 elevado a -143\n",
    "contra 10 elevado a -142 💪\n",
    "\n",
    "Lo que hace es olvidarse de los valores y quedarse con el orden: pone las\n",
    "1.543 ventas en fila y mira si las de un grupo tienden a estar más arriba. Como\n",
    "no usa los montos, ningún atípico la despeina.\n",
    "\n",
    "Mi criterio práctico, por si te sirve: si las dos coinciden, reporta la t que\n",
    "todo el mundo entiende. Si discrepan, quédate con Mann-Whitney y mira qué está\n",
    "haciendo la cola 👀"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 7. La misma diferencia con cuatro tamaños\n",
    "\n",
    "Compara horeca contra minimarket con 20, 60, 200 y 600 por grupo, y mira cómo cambia el valor p."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "ge = np.random.default_rng(1)\n",
    "for n in [20, 60, 200, 600]:\n",
    "    a2 = ge.choice(horeca, n, replace=False)\n",
    "    b2 = ge.choice(minimarket, n, replace=False)\n",
    "    print('con %3d por grupo: diferencia %8.2f   p = %.4f'\n",
    "          % (n, a2.mean() - b2.mean(), stats.ttest_ind(a2, b2).pvalue))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "con  20 por grupo: diferencia     0.10   p = 0.5393\n",
    "con  60 por grupo: diferencia     0.02   p = 0.8556\n",
    "con 200 por grupo: diferencia     0.07   p = 0.1808\n",
    "con 600 por grupo: diferencia     0.09   p = 0.0014\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "La diferencia se queda en 0,1 y el valor p se desploma 😬\n",
    "\n",
    "Mira las dos columnas juntas: el efecto es prácticamente el mismo en las cuatro filas, y el p pasa de 0,54 a 0,0014. Lo único que cambió fue cuánta gente miramos.\n",
    "\n",
    "**El valor p mide evidencia, no tamaño.** Con muestras grandes, diferencias que no le importan a nadie salen significativas, y por eso el capítulo 14 existe 📉"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 8. Barajando etiquetas quinientas veces\n",
    "\n",
    "Mezcla los dos grupos al azar quinientas veces y cuenta cuántas dan un valor p por debajo de 0,05."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "g3 = np.random.default_rng(5)\n",
    "todos = np.concatenate([horeca, minimarket])\n",
    "falsos = 0\n",
    "for _ in range(500):\n",
    "    mezcla = g3.permutation(todos)\n",
    "    corte = len(horeca)\n",
    "    falsos += stats.ttest_ind(mezcla[:corte], mezcla[corte:]).pvalue < 0.05\n",
    "print('de 500 particiones al azar, salen significativas: %d' % falsos)\n",
    "print('o sea el %.1f%%, y lo esperado es el 5%%' % (falsos / 500 * 100))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "de 500 particiones al azar, salen significativas: 15\n",
    "o sea el 3.0%, y lo esperado es el 5%\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "El 3,0% donde se esperaba el 5% 💚\n",
    "\n",
    "Aquí no hay ninguna diferencia real: las etiquetas están barajadas, así que los dos grupos son el mismo grupo partido al azar. Y aun así quince de las quinientas salen significativas. **Eso es lo que promete el 0,05**: equivocarse cinco veces de cada cien cuando no hay nada.\n",
    "\n",
    "Que salga 3,0 y no 5,0 es el azar de hacer solo 500 pruebas. Corre la celda con otra semilla y vas a ver el número bailar alrededor del cinco, que es justo la lección 🎲"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## La misma diferencia con dos conclusiones opuestas"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Y ahora la trampa del capítulo, que es la que más decisiones malas ha producido de todo el libro 🔬"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### La trampa\n",
    "\n",
    "Comparas dos canales, sale p mayor que 0,05, y escribes en el informe que no hay diferencia entre ellos.\n",
    "\n",
    "```\n",
    "# los dos canales enteros\n",
    "# WhatsApp 0.655  vs  Marketplace 0.461\n",
    "# n = 719 y 763      p = 9.4e-14\n",
    "\n",
    "# la MISMA comparación con 60 y 60\n",
    "# 0.650  vs  0.483\n",
    "# p = 0.0973\n",
    "```\n",
    "\n",
    "**Qué está mal**\n",
    "\n",
    "La misma diferencia de verdad, y dos conclusiones opuestas 🔬 Lo único que cambió fue cuántas filas miré.\n",
    "\n",
    "Un p alto no dice \"son iguales\". Dice **\"con estos datos no se ve\"**, que es otra cosa completamente distinta. Con 60 filas por grupo, una diferencia de 17 puntos, que es enorme, se queda sin fuerza para demostrarse.\n",
    "\n",
    "Y esto se convierte en decisiones malas todo el tiempo: se prueba algo con poca gente, sale p alto, y se archiva como que no funciona. No se demostró que no funcione. No se demostró nada.\n",
    "\n",
    "Cuando te salga un p alto, mira dos cosas antes de escribir la conclusión: **el tamaño de la diferencia** y **su intervalo de confianza**. Si el intervalo va de -2% a +20%, lo honesto es decir que no sabes, no que da igual."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Comprueba que lo tienes\n",
    "\n",
    "Un valor p de 0,0155, ¿qué significa exactamente?\n",
    "\n",
    "a) Que si no hubiera efecto, el 1,55% de las veces vería algo así de grande\n",
    "\n",
    "b) Que hay un 1,55% de probabilidad de que sea casualidad\n",
    "\n",
    "c) Que hay un 98,45% de probabilidad de que la diferencia sea real\n",
    "\n",
    "d) Que el efecto es pequeño\n",
    "\n",
    "---\n",
    "\n",
    "**La correcta es la a.**\n",
    "\n",
    "*b)* Es la más común y está al revés: el p se calcula suponiendo que ES casualidad.\n",
    "\n",
    "*c)* El p no puede decir eso: se calcula suponiendo que no hay diferencia.\n",
    "\n",
    "*d)* El p no mide tamaño. Mezcla el efecto con cuántos datos tienes.\n",
    "\n",
    "De 10.000 mundos sin efecto, 155 produjeron una diferencia tan grande como la observada."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Lo que te llevas"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 🃏 Un valor p es contar: de 10.000 mundos sin efecto, ¿cuántos producen algo\n",
    "tan grande como lo tuyo? Aquí 155, o sea p = 0,0155.\n",
    "\n",
    "- ⚡ La fórmula es el atajo de eso. La permutación dio 0,0155 y la prueba t\n",
    "0,0118.\n",
    "\n",
    "- 🚫 Un p alto no demuestra que no haya diferencia. Ausencia de evidencia no es\n",
    "evidencia de ausencia.\n",
    "\n",
    "- 🎯 Alfa = 0,05 significa equivocarte 1 de cada 20 veces cuando no hay nada.\n",
    "Con 1.000 comparaciones vacías salieron 57 significativas.\n",
    "\n",
    "- ❌ El p no es la probabilidad de que sea casualidad, ni el tamaño del efecto,\n",
    "ni una medida de importancia.\n",
    "\n",
    "- 🎰 Con muestras chicas el p es un sorteo: el mismo efecto dio 0,2000, 0,3626,\n",
    "0,0392 y 0,1263 según qué 100 filas tocaran.\n",
    "\n",
    "- 👻 Un p de `nan` no es \"no significativo\", es \"no calculé nada\". Y\n",
    "llega sin avisar en cuanto hay nulos.\n",
    "\n",
    "Y si de todo el capítulo te llevas una sola frase, que sea esta:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "El valor p mide evidencia, no importancia. Y no dice nada de la\n",
    "probabilidad de que tengas razón."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Y sacar los dos grupos que vas a comparar casi nunca es un filtro de pandas en\n",
    "la vida real: es una consulta contra la base. Eso está en el\n",
    "[libro de SQL](https://missyera.com/guias/sql-desde-cero/) 🗃️"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Qué viene ahora"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ya sabes qué es un valor p. En el capítulo 13 vemos las cuatro pruebas\n",
    "concretas que cubren el 90% de los casos reales, y sobre todo cómo elegir cuál\n",
    "toca, que es donde se atasca todo el mundo 🧰"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Preguntas frecuentes"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "¿Qué es la hipótesis nula?La afirmación aburrida: que no pasa nada, que las dos cosas son iguales, que la diferencia es azar. La prueba se monta para ver si hay evidencia suficiente para descartarla.\n",
    "\n",
    "¿Qué es el valor p?La probabilidad de ver una diferencia como la tuya, o mayor, si la hipótesis nula fuera cierta. No es la probabilidad de que tu hipótesis sea verdad, y esa confusión es la más común de la estadística.\n",
    "\n",
    "¿Qué significa que el valor p sea menor a 0,05?Que un resultado así sería raro si no pasara nada, así que se descarta la hipótesis nula. El 0,05 es una convención y no una ley de la naturaleza.\n",
    "\n",
    "¿Qué es el error tipo I y el tipo II?El tipo I es decir que hay diferencia cuando no la hay. El tipo II es no verla cuando sí la hay. Bajar uno sube el otro, y elegir cuál te duele más es una decisión de negocio."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "Ese era el capítulo 12 de **Estadística desde cero**. El texto completo, con las salidas de cada bloque, está en https://missyera.com/guias/estadistica-desde-cero/prueba-de-hipotesis/\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
}
