{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# De la muestra a la población\n",
    "\n",
    "Intervalos de confianza, lo que de verdad significan, y por qué dos intervalos que se solapan pueden ser una diferencia real.\n",
    "\n",
    "Cuaderno de práctica del capítulo 10 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/intervalos-de-confianza/\n",
    "\n",
    "Los ejercicios están al final y traen una celda vacía debajo de cada uno. Las\n",
    "respuestas viven en el cuaderno de soluciones, y merece la pena pelearse un\n",
    "rato antes de abrirlo 💛"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Antes de empezar\n",
    "\n",
    "Esta celda baja el ayudante que corrige tus ejercicios. Después, en cada\n",
    "ejercicio que se pueda corregir solo, vas a ver `%%revisa` arriba de la celda:\n",
    "escribe tu respuesta debajo, ejecuta, y te digo si te salió 💛"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import urllib.request\n",
    "\n",
    "# El ayudante de los cuadernos. Trae la corrección de los ejercicios y, en los\n",
    "# capítulos de consola, la celda mágica que ejecuta los comandos. Se baja en\n",
    "# vez de venir pegado aquí para que siempre sea el último.\n",
    "urllib.request.urlretrieve(\n",
    "    \"https://missyera.com/static/cuadernos/revisa.py\", \"revisa.py\")\n",
    "import revisa\n",
    "revisa.carga({\n",
    "    1: \"Qm9kZWdhICAgICAgbj03MDcgIDM3LjQ4JSArLy0gMy41NyBwdW50b3MKSG9yZWNhICAgICAgbj03NDIgIDYzLjIxJSArLy0gMy40NyBwdW50b3MKTWF5b3Jpc3RhICAgbj03NTAgIDcyLjQwJSArLy0gMy4yMCBwdW50b3MKTWluaW1hcmtldCAgbj04MDEgIDU2LjkzJSArLy0gMy40MyBwdW50b3M=\",\n",
    "    2: \"cGFyYSArLy0gNSBwdW50b3MgaGFjZW4gZmFsdGEgICAgIDM3NSB2ZW50YXMKcGFyYSArLy0gMyBwdW50b3MgaGFjZW4gZmFsdGEgICAgMTA0MSB2ZW50YXMKcGFyYSArLy0gMiBwdW50b3MgaGFjZW4gZmFsdGEgICAgMjM0MyB2ZW50YXMKcGFyYSArLy0gMSBwdW50b3MgaGFjZW4gZmFsdGEgICAgOTM3MiB2ZW50YXM=\",\n",
    "    3: \"bWVkaWFuYSBvYnNlcnZhZGE6IDUzMy42MwppbnRlcnZhbG8gZGVsIDk1JTogWzUwOS44MiwgNTUyLjg2XQplcnJvciBlc3RhbmRhciBkZSBsYSBtZWRpYW5hOiAxMS4zNg==\",\n",
    "    4: \"bWF5b3Jpc3RhOiAxODU2LjM0IHwgYm9kZWdhOiAxNzguNzAKZGlmZXJlbmNpYTogMTY3Ny42NCBzb2xlcwppbnRlcnZhbG8gZGVsIDk1JTogWzE2MjUuODksIDE3MjkuMzld\",\n",
    "    5: \"IDE6IFsgNjE2LjI5LCAgOTI2LjM1XSAgb2sKIDI6IFsgNzQxLjY1LCAxMDUzLjIwXSAgb2sKIDM6IFsgNjk4LjA0LCAxMDE2LjczXSAgb2sKIDQ6IFsgODI1LjIxLCAxMTQwLjg1XSAgRkFMTEEKIDU6IFsgNTg4LjgxLCAgODU1LjE2XSAgb2sKIDY6IFsgNjc3Ljc3LCAgOTgzLjE0XSAgb2sKIDc6IFsgNjU3LjYyLCAgOTMyLjI2XSAgb2sKIDg6IFsgNjU1LjE0LCAgOTMyLjU2XSAgb2sKIDk6IFsgNzI5LjA5LCAxMDI1Ljg0XSAgb2sKMTA6IFsgNzA4LjkyLCAgOTgxLjIyXSAgb2sKMTE6IFsgNTU0Ljg4LCAgODI5Ljk4XSAgb2sKMTI6IFsgNjk1LjczLCAgOTk3LjQ2XSAgb2sKMTM6IFsgNzIwLjY4LCAxMDQ5LjM1XSAgb2sKMTQ6IFsgNjk4LjkyLCAgOTY0Ljk2XSAgb2sKMTU6IFsgNjA3LjIyLCAgOTAyLjkyXSAgb2sKMTY6IFsgNjM5LjYzLCAgOTA1LjYxXSAgb2sKMTc6IFsgNjIyLjkwLCAgOTIxLjY1XSAgb2sKMTg6IFsgNzEwLjc3LCAxMDE1LjM4XSAgb2sKMTk6IFsgNjcyLjc3LCAgOTgxLjAxXSAgb2sKMjA6IFsgNjU0LjI0LCAgOTQwLjY5XSAgb2sKCmZhbGxhcm9uIDEgZGUgMjA=\",\n",
    "    6: \"dGFzYSBkZSBjaWVycmU6IDU3LjglIChlbnRyZSA1Ni4wJSB5IDU5LjUlLCBjb24gMzAwMCBjYXNvcykKY2llcnJlIHBvciBXaGF0c0FwcDogNjUuNSUgKGVudHJlIDYyLjAlIHkgNjkuMCUsIGNvbiA3MTkgY2Fzb3MpCmNpZXJyZSBlbiBMaW1hOiA1OC40JSAoZW50cmUgNTMuOSUgeSA2Mi44JSwgY29uIDQ3MSBjYXNvcykKY2llcnJlIGVuIExpbWEgcG9yIFdoYXRzQXBwOiA2Mi45JSAoZW50cmUgNTQuNCUgeSA3MS40JSwgY29uIDEyNCBjYXNvcyk=\",\n",
    "    7: \"Y29uICAgIDMwIHBlZGlkb3M6IGRlICA2ODAuNTggYSAxMjg5LjYyLCBtYXJnZW4gKy8tIDMwNC41Mgpjb24gICAxMDAgcGVkaWRvczogZGUgIDY3My41NCBhICA5OTQuODgsIG1hcmdlbiArLy0gMTYwLjY3CmNvbiAgIDUwMCBwZWRpZG9zOiBkZSAgNzg1LjcyIGEgIDkyNy44NCwgbWFyZ2VuICsvLSAgNzEuMDYKY29uICAzMDAwIHBlZGlkb3M6IGRlICA3NzYuODQgYSAgODMwLjY4LCBtYXJnZW4gKy8tICAyNi45Mg==\",\n",
    "    8: \"YWwgODAlOiBkZSAgNzg2LjE2IGEgIDgyMS4zNiwgYW5jaG8gIDM1LjIwCmFsIDkwJTogZGUgIDc4MS4xNyBhICA4MjYuMzUsIGFuY2hvICA0NS4xOAphbCA5NSU6IGRlICA3NzYuODQgYSAgODMwLjY4LCBhbmNobyAgNTMuODQKYWwgOTklOiBkZSAgNzY4LjM3IGEgIDgzOS4xNSwgYW5jaG8gIDcwLjc3\",\n",
    "}, lenguaje=\"python\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Tienes 3.000 ventas y calculas que el monto promedio es 803,76 soles.\n",
    "\n",
    "Pero esas 3.000 no son todas las ventas del mundo: son las que te tocaron. Si\n",
    "el mes que viene sacas otras 3.000, el promedio va a salir distinto. Entonces,\n",
    "¿de cuánto es el promedio *de verdad*? 🤷\n",
    "\n",
    "La respuesta honesta no es un número, es un rango. Eso es un intervalo de\n",
    "confianza, y este capítulo va de calcularlo, entenderlo y no contarlo mal."
   ]
  },
  {
   "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",
    "m = v['monto']\n",
    "n = len(m)\n",
    "\n",
    "error_estandar = m.std() / np.sqrt(n)\n",
    "\n",
    "print('promedio:        %.4f' % m.mean())\n",
    "print('error estandar:  %.4f' % error_estandar)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ese error estándar es el del capítulo 8: cuánto se mueve un promedio de\n",
    "muestra en muestra. 13,73 soles."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "EE=sn\n",
    "\n",
    "cuánto se mueve un promedio de muestra en muestra, que baja con la raíz de cuántos datos tengas"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Y una pregunta que vale para toda tu vida laboral: **¿cuántas veces has entregado un número sin decir cuánto se puede mover?** El margen de error no es un adorno académico: es lo que separa un dato de una apuesta 📊"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## El intervalo, en una línea"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "bajo, alto = stats.t.interval(0.95, n - 1, m.mean(), error_estandar)\n",
    "\n",
    "print('promedio: %.2f' % m.mean())\n",
    "print('intervalo del 95%%: de %.2f a %.2f' % (bajo, alto))\n",
    "print('margen de error: +/- %.2f soles' % ((alto - bajo) / 2))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ahí lo tienes: **el monto promedio está entre 776,84 y 830,68\n",
    "soles** 📊\n",
    "\n",
    "Ese 1,96 que multiplica el error estándar (aquí lo pone la t por dentro) es el\n",
    "número mágico del 95%. Si quisieras el 99% sería 2,58, y el intervalo saldría\n",
    "más ancho: más seguridad cuesta más rango.\n",
    "\n",
    "La regla rápida que puedes hacer de cabeza: **margen de error igual a\n",
    "dos errores estándar** 🧮"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "IC95%=x¯±1,96·sn\n",
    "\n",
    "el promedio más menos dos errores estándar, que es de donde sale el margen de error de las encuestas"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Lo que significa, y lo que no"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Esta es la parte que casi todo el mundo cuenta mal, incluida yo durante\n",
    "años 🙋\n",
    "\n",
    "**Mal:** \"hay un 95% de probabilidad de que el promedio real esté\n",
    "entre 776,84 y 830,68\".\n",
    "\n",
    "**Bien:** \"si repitiera este cálculo muchas veces con muestras\n",
    "distintas, el 95% de los intervalos que saldrían contendrían el promedio real\".\n",
    "\n",
    "La diferencia parece de abogados y no lo es. El promedio real es un número\n",
    "fijo: o está dentro de tu intervalo o no está. **Lo que tiene el 95% es el\n",
    "método, no el intervalo concreto que te salió**.\n",
    "\n",
    "Y como esto se entiende mejor viéndolo, vamos a hacerlo:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "generador = np.random.default_rng(7)\n",
    "verdadera = m.mean()\n",
    "tamano = 50\n",
    "contiene = 0\n",
    "\n",
    "for _ in range(1000):\n",
    "    muestra = generador.choice(m.values, tamano)\n",
    "    ee = muestra.std(ddof=1) / np.sqrt(tamano)\n",
    "    lo, hi = stats.t.interval(0.95, tamano - 1, muestra.mean(), ee)\n",
    "    contiene += (lo <= verdadera <= hi)\n",
    "\n",
    "print('de 1000 intervalos del 95%%, contienen el promedio real: %d' % contiene)\n",
    "print('o sea el %.1f%%' % (contiene / 10))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "92,9% en vez de 95%. Se queda corto 🤔\n",
    "\n",
    "Y ese \"casi\" tiene explicación, que es de las cosas más útiles del capítulo.\n",
    "Vamos a probar con distintos tamaños:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "for tamano in [20, 50, 200, 1000]:\n",
    "    contiene = 0\n",
    "    for _ in range(1000):\n",
    "        muestra = generador.choice(m.values, tamano)\n",
    "        ee = muestra.std(ddof=1) / np.sqrt(tamano)\n",
    "        lo, hi = stats.t.interval(0.95, tamano - 1, muestra.mean(), ee)\n",
    "        contiene += (lo <= verdadera <= hi)\n",
    "    print('con muestras de %4d -> cobertura real %.1f%%' % (tamano, contiene / 10))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Con muestras de 20 o 50, tu intervalo del 95% acierta el 93%** 😬\n",
    "\n",
    "O sea que te está mintiendo un poco: crees que fallas 1 de cada 20 y fallas 1\n",
    "de cada 15. Y no hay ningún error en el cálculo. Solo cuando llegas a 1.000 la\n",
    "cobertura sube al 95,9% y la promesa se cumple.\n",
    "\n",
    "La causa es la cola del capítulo 5. La fórmula supone que los promedios ya se\n",
    "han acampanado, y con 20 ventas de una distribución tan torcida todavía no lo\n",
    "están (capítulo 8: con 30 la asimetría seguía en 0,3223).\n",
    "\n",
    "Compáralo con `unidades`, que sí era acampanada:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "u = v['unidades'].values\n",
    "verdadera_u = u.mean()\n",
    "\n",
    "for tamano in [20, 50]:\n",
    "    contiene = 0\n",
    "    for _ in range(1000):\n",
    "        muestra = generador.choice(u, tamano)\n",
    "        ee = muestra.std(ddof=1) / np.sqrt(tamano)\n",
    "        lo, hi = stats.t.interval(0.95, tamano - 1, muestra.mean(), ee)\n",
    "        contiene += (lo <= verdadera_u <= hi)\n",
    "    print('unidades, muestras de %3d -> cobertura %.1f%%' % (tamano, contiene / 10))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**95,2% con solo 20 datos.** Justo lo prometido, con la cuarta\n",
    "parte de la muestra que le hacía falta al monto 🔔\n",
    "\n",
    "La forma de los datos importa más que la cantidad. Y date cuenta de lo que eso\n",
    "significa en la práctica: el mismo tamaño de muestra te da un intervalo honesto\n",
    "o uno optimista según qué columna estés midiendo."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## El intervalo de una proporción"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "El caso más frecuente en la vida real: \"el 57,77% de las ventas se cierra,\n",
    "¿con cuánto margen?\".\n",
    "\n",
    "Aquí el error estándar tiene su propia fórmula, la que sacamos en el capítulo\n",
    "4:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "EEp=p(1−p)n\n",
    "\n",
    "el error estándar de un porcentaje, que es máximo cuando el reparto está en la mitad y se encoge cuando se acerca a cero o a uno"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "p = v['compro'].mean()\n",
    "ee_p = np.sqrt(p * (1 - p) / n)\n",
    "\n",
    "print('proporcion: %.4f' % p)\n",
    "print('error estandar: %.6f' % ee_p)\n",
    "print('intervalo del 95%%: %.4f a %.4f' % (p - 1.96 * ee_p, p + 1.96 * ee_p))\n",
    "print('o sea: %.2f%% +/- %.2f puntos' % (100 * p, 100 * 1.96 * ee_p))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "57,77% con un margen de 1,77 puntos. Ese \"±1,8 puntos\" es exactamente lo que\n",
    "sale en las encuestas electorales 🗳️"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## El error del capítulo"
   ]
  },
  {
   "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.t.interval(95, n - 1, m.mean(), error_estandar)\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: alpha must be between 0 and 1 inclusive\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Le pedí el 95 en vez del 0,95. Menos mal que avisa 🙏\n",
    "\n",
    "Porque el mismo despiste en la otra dirección **no** avisa:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print('pidiendo 0.95:', np.round(stats.t.interval(0.95, n - 1, m.mean(), error_estandar), 2))\n",
    "print('pidiendo 0.05:', np.round(stats.t.interval(0.05, n - 1, m.mean(), error_estandar), 2))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Si por error pides 0,05 en vez de 0,95, te devuelve un intervalo\n",
    "**estrechísimo** y perfectamente válido: el intervalo del 5% 😱\n",
    "\n",
    "Y ese sí que se cuela en un informe, porque un margen de error chiquito es\n",
    "justo lo que uno quiere ver. Cuidado con los resultados que te gustan\n",
    "demasiado 🍬"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## La trampa de los intervalos que se solapan"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Y ahora lo más importante del capítulo, que es un error que he visto en\n",
    "informes serios.\n",
    "\n",
    "Comparamos dos segmentos:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "for seg in ['Horeca', 'Minimarket']:\n",
    "    g = v.loc[v['segmento'] == seg, 'compro']\n",
    "    pp = g.mean()\n",
    "    e = np.sqrt(pp * (1 - pp) / len(g))\n",
    "    print('%-11s n=%3d  p=%.4f  IC [%.4f, %.4f]'\n",
    "          % (seg, len(g), pp, pp - 1.96 * e, pp + 1.96 * e))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Los intervalos **se solapan**: Horeca llega hasta 0,5974 por\n",
    "abajo y Minimarket sube hasta 0,6036.\n",
    "\n",
    "La conclusión que casi todo el mundo saca: \"se solapan, así que no hay\n",
    "diferencia\". Vamos a comprobarlo calculando el intervalo *de la\n",
    "diferencia*, que es lo que había que hacer:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = v.loc[v['segmento'] == 'Horeca', 'compro']\n",
    "b = v.loc[v['segmento'] == 'Minimarket', 'compro']\n",
    "\n",
    "pa, pb = a.mean(), b.mean()\n",
    "ea = np.sqrt(pa * (1 - pa) / len(a))\n",
    "eb = np.sqrt(pb * (1 - pb) / len(b))\n",
    "ee_dif = np.sqrt(ea ** 2 + eb ** 2)\n",
    "dif = pa - pb\n",
    "\n",
    "print('diferencia: %.4f' % dif)\n",
    "print('intervalo del 95%%: [%.4f, %.4f]'\n",
    "      % (dif - 1.96 * ee_dif, dif + 1.96 * ee_dif))\n",
    "print('contiene el cero:', (dif - 1.96 * ee_dif) <= 0 <= (dif + 1.96 * ee_dif))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**El intervalo de la diferencia no contiene el cero.** O sea que\n",
    "la diferencia es real, aunque los intervalos individuales se solapen 🤯\n",
    "\n",
    "Por qué pasa: el error estándar de la diferencia no es la suma de los dos,\n",
    "es la raíz de la suma de los cuadrados, que sale más chica. Sumar dos incertidumbres\n",
    "\"a lo bruto\" exagera."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "EEd=EE12+EE22\n",
    "\n",
    "la incertidumbre de una diferencia no es la suma de las dos, es la raíz de la suma de sus cuadrados, y por eso sale más chica"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Regla:** para comparar dos grupos, calcula el intervalo de la\n",
    "diferencia. Nunca mires si los individuales se tocan 📏"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Y dos más, y el primero es EL error de este capítulo"
   ]
  },
  {
   "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.t.interval(95, len(m) - 1, m.mean(), error_estandar)\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: alpha must be between 0 and 1 inclusive\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "El 95% se escribe **0,95** y no 95. Este lo he visto tantas veces que casi merece un capítulo propio, y menos mal que revienta: si scipy aceptara el 95 sin quejarse, te devolvería un intervalo absurdo y no habría forma de notarlo."
   ]
  },
  {
   "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.bootstrap(m, np.mean)\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",
    "AxisError: `axis` is out of bounds for array of dimension 0\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Y este te presenta al capítulo siguiente. `scipy` trae su propio\n",
    "bootstrap, y se queja porque quiere **una secuencia de muestras** y\n",
    "le diste la muestra: hay que escribir `stats.bootstrap((m,), np.mean)`,\n",
    "con esa coma que convierte a `m` en una tupla de un elemento. Es una\n",
    "coma y es la diferencia entre que funcione y que no 🥾"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Practica 💪"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1. El margen de error de cada segmento\n",
    "\n",
    "Calcula el intervalo de la tasa de compra de los cuatro\n",
    "segmentos. ¿Cuál tiene el margen más ancho y por qué?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 1\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. ¿Cuántos datos necesito para un margen de 1 punto?\n",
    "\n",
    "Despeja n de la fórmula del margen de error de una\n",
    "proporción y calcula cuántas ventas hacen falta para varios márgenes."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 2\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3. Un intervalo sin fórmulas: bootstrap\n",
    "\n",
    "La mediana no tiene fórmula sencilla de error estándar.\n",
    "Calcula su intervalo remuestreando."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 3\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4. El intervalo de una diferencia de medias\n",
    "\n",
    "¿Cuánto más vende un mayorista que una bodega? Da la\n",
    "diferencia con su intervalo."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 4\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 5. Fabrica el gráfico de cobertura a mano\n",
    "\n",
    "Genera 20 intervalos de muestras de 100 ventas y dibuja\n",
    "cuáles contienen el promedio real."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 5\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 6. El resumen que sí se puede llevar a una reunión\n",
    "\n",
    "Escribe una función que dé una proporción con su margen en\n",
    "lenguaje de persona."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 6\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 7. Cuánto encoge el margen al crecer la muestra\n",
    "\n",
    "Calcula el intervalo del promedio con 30, 100, 500 y todos los pedidos, y mira cómo cambia el margen."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 7\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 8. El precio de estar más seguro\n",
    "\n",
    "Saca el intervalo al 80%, 90%, 95% y 99% y compara los anchos."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 8\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Los intervalos se tocan y la diferencia es real"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Antes de cerrar el capítulo, el atajo más repetido sobre intervalos, y por qué es falso 😬"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### La trampa\n",
    "\n",
    "Tienes los intervalos de los dos canales y quieres el de la diferencia. Restas los extremos, que es lo que parece razonable.\n",
    "\n",
    "```\n",
    "# WhatsApp 0.655  IC [0.620, 0.690]\n",
    "# Tienda   0.620  IC [0.585, 0.655]\n",
    "\n",
    "# restando extremos: [0.620 - 0.655, 0.690 - 0.585]\n",
    "#                  = [-0.035, 0.105]\n",
    "\n",
    "# el de la diferencia, bien calculado:\n",
    "#                  = [-0.014, 0.085]\n",
    "```\n",
    "\n",
    "**¿Qué está mal?** La respuesta está en el cuaderno de soluciones. Míralo tú primero."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Comprueba que lo tienes\n",
    "\n",
    "Dos segmentos tienen intervalos de confianza que se solapan. ¿Hay diferencia entre ellos?\n",
    "\n",
    "a) No se sabe: hay que calcular el intervalo de la diferencia\n",
    "\n",
    "b) No, porque si se solapan la diferencia no es real\n",
    "\n",
    "c) Sí, porque los centros son distintos\n",
    "\n",
    "d) Depende de cuánto se solapen"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Lo que te llevas"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 📏 Margen de error = dos errores estándar. Aquí el monto promedio es 803,76\n",
    "con un margen de ±26,92.\n",
    "\n",
    "- 🎯 El 95% es del método, no de tu intervalo. Tú tienes uno y no sabes si es\n",
    "de los buenos.\n",
    "\n",
    "- ⚠️ Con muestras chicas de una columna con cola, el intervalo del 95% acierta\n",
    "el 93%. Con `unidades`, que es acampanada, acierta el 95,2% ya con\n",
    "20 datos.\n",
    "\n",
    "- 🔗 Intervalos que se solapan NO significan que no haya diferencia. Horeca y\n",
    "Minimarket se solapan y su diferencia va de 0,0140 a 0,1116, sin tocar el\n",
    "cero.\n",
    "\n",
    "- 🥾 El bootstrap da intervalos de cualquier cosa sin fórmulas. La mediana\n",
    "salió más precisa que la media: 11,36 contra 13,73.\n",
    "\n",
    "- 🧮 Para un margen de 3 puntos hacen falta 1.042 casos; para 1 punto, 9.375.\n",
    "\n",
    "- 🔢 Un porcentaje sin su número de casos no significa nada.\n",
    "\n",
    "Y si de todo el capítulo te llevas una sola frase, que sea esta:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Un número sin intervalo es una opinión con decimales."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Y esta idea de dar un rango en vez de un número es la misma que hay detrás de\n",
    "la validación cruzada: un modelo tampoco tiene una nota, tiene un rango. Está en\n",
    "el [libro de machine learning](https://missyera.com/guias/machine-learning-desde-cero/) 🎯"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Qué viene ahora"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Con el intervalo de la diferencia ya casi hemos hecho una prueba de\n",
    "hipótesis sin darnos cuenta: mirábamos si el cero estaba dentro. En el capítulo 12 le ponemos nombre, y sobre todo desmontamos el valor p, que es el número peor\n",
    "entendido de toda la estadística 🎓"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Preguntas frecuentes"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "¿Qué es un intervalo de confianza?Un rango donde es razonable que esté el valor de verdad, dado lo que viste en la muestra. Se reporta en vez de un número solo porque el número solo esconde que hubo muestra.\n",
    "\n",
    "¿Cómo se interpreta un intervalo de confianza del 95%?No es que haya 95% de probabilidad de que el valor esté ahí. Es que si repitieras el muestreo muchas veces, 95 de cada 100 intervalos calculados así contendrían el valor real.\n",
    "\n",
    "¿Qué es el margen de error?La mitad del ancho del intervalo. Cuando una encuesta dice \"más o menos 3 puntos\", eso es el margen de error.\n",
    "\n",
    "¿Cómo hago el intervalo más angosto?Con más datos, y crece con la raíz: para que el intervalo mida la mitad hace falta cuatro veces la muestra. Por eso pasar de mil a dos mil encuestados sirve menos de lo que la gente espera."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "Ese era el capítulo 10 de **Estadística desde cero**. El texto completo, con las salidas de cada bloque, está en https://missyera.com/guias/estadistica-desde-cero/intervalos-de-confianza/\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
}
