{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Probabilidad, lo justo y necesario\n",
    "\n",
    "Condicional, independencia y Bayes. Con el error de dar la vuelta a una probabilidad, que cuesta campañas enteras.\n",
    "\n",
    "Cuaderno de práctica del capítulo 7 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/probabilidad/\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: \"ICAgICAgICAgICBQKGNvbXByYSkgIHZlbnRhcwpjYW5hbApNYXJrZXRwbGFjZSAgICAgMC40NjEzICAgICA3NjMKV2ViICAgICAgICAgICAgIDAuNTgwOCAgICAgNzkyClRpZW5kYSAgICAgICAgICAwLjYxOTggICAgIDcyNgpXaGF0c0FwcCAgICAgICAgMC42NTUxICAgICA3MTkKCmVsIG1lam9yIHN1cGVyYSBhbCBwZW9yIGVuIDE5LjQgcHVudG9z\",\n",
    "    2: \"Y2l1ZGFkICAgICAgc2UgZGVzdmlhIGhhc3RhICAgMi41JSBkZSBsYSBpbmRlcGVuZGVuY2lhCmNhdGVnb3JpYSAgIHNlIGRlc3ZpYSBoYXN0YSAgIDMuMiUgZGUgbGEgaW5kZXBlbmRlbmNpYQpjYW5hbCAgICAgICBzZSBkZXN2aWEgaGFzdGEgIDIwLjElIGRlIGxhIGluZGVwZW5kZW5jaWEKc2VnbWVudG8gICAgc2UgZGVzdmlhIGhhc3RhICAzNS4xJSBkZSBsYSBpbmRlcGVuZGVuY2lh\",\n",
    "    3: \"UCh3aGF0c2FwcCB8IGNvbXByYSkgY29uIEJheWVzOiAwLjI3MTgKY29udGFuZG86ICAgICAgICAgICAgICAgICAgICAgICAwLjI3MTg=\",\n",
    "    4: \"ZmlsYXMgY29uIHNhdGlzZmFjY2lvbjogMjc2OQpQKGFsYXJtYSkgICAgICAgICAgICAgICA9IDAuMzk2MgpQKG5vIGNlcnJvKSAgICAgICAgICAgICA9IDAuNDI1OAoKUChhbGFybWEgfCBubyBjZXJybykgICAgPSAwLjQ3MjQKUChhbGFybWEgfCBzaSBjZXJybykgICAgPSAwLjMzOTYKUChubyBjZXJybyB8IGFsYXJtYSkgICAgPSAwLjUwNzc=\",\n",
    "    5: \"UChjYXJhKSAgICAgICAgICA9IDAuNTAzMwpQKGNvbXByYSB8IGNhcmEpID0gMC41NzU1ClAoY29tcHJhKSAgICAgICAgPSAwLjU3NzcKCmp1bnRhcyAwLjI4OTcgfCBwcm9kdWN0byAwLjI5MDggfCBzZSBkZXN2aWEgLTAuMzgl\",\n",
    "    6: \"ZGlyZWN0bzogMC4wNDY2NjcKY2FkZW5hOiAgMC4wNDY2NjcKCnNvbiAxNDAgdmVudGFzIGRlIDMwMDA=\",\n",
    "    7: \"Y29tcHJvICAgICAgICAgMCAgICAgMQpzZWdtZW50bwpCb2RlZ2EgICAgICA2Mi41ICAzNy41CkhvcmVjYSAgICAgIDM2LjggIDYzLjIKTWF5b3Jpc3RhICAgMjcuNiAgNzIuNApNaW5pbWFya2V0ICA0My4xICA1Ni45CgpjaWVycmEgbWFzIHNlZ3VpZG86IE1heW9yaXN0YQpjaWVycmEgbWVub3M6ICAgICAgIEJvZGVnYQ==\",\n",
    "    8: \"UChXZWIpICAgICAgICAgICA9IDAuMjY0MApQKGNpZXJyYSkgICAgICAgID0gMC41Nzc3CnNpIGZ1ZXJhbiBpbmRlcGVuZGllbnRlcywgUChsYXMgZG9zKSA9IDAuMTUyNQpQKGxhcyBkb3MpIGRlIHZlcmRhZCAgICAgICAgICAgICAgICAgPSAwLjE1MzM=\",\n",
    "}, lenguaje=\"python\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Empieza la segunda mitad del libro 🎬\n",
    "\n",
    "Hasta ahora describíamos lo que teníamos delante. A partir de aquí vamos a\n",
    "afirmar cosas sobre lo que *no* medimos, y para eso hace falta un poco de\n",
    "probabilidad.\n",
    "\n",
    "Poca, te lo prometo. Nada de urnas con bolas ni de barajas. Tres ideas, y las\n",
    "tres se calculan con la misma tabla de ventas de siempre."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\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",
    "print('P(compra)    = %.4f' % v['compro'].mean())\n",
    "print('P(mayorista) = %.4f' % (v['segmento'] == 'Mayorista').mean())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ahí tienes la única definición de probabilidad que vas a necesitar:\n",
    "**la proporción de veces que pasa algo**. Y ya sabes calcularla\n",
    "desde el capítulo 2, porque es la media de una columna de ceros y unos 😌\n",
    "\n",
    "Y dime: **¿te has creído alguna vez un resultado de laboratorio sin preguntar cuánta gente tiene esa enfermedad?** Es el mismo error que vamos a ver acá, y cuesta mucho más caro en datos 🎲"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Regla 1: la suma, con su descuento"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "¿Cuál es la probabilidad de que una venta sea de un mayorista\n",
    "**o** venga por WhatsApp?\n",
    "\n",
    "La tentación es sumar. Vamos a ver:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "mayorista = v['segmento'] == 'Mayorista'\n",
    "whatsapp = v['canal'] == 'WhatsApp'\n",
    "\n",
    "print('P(mayorista)        = %.4f' % mayorista.mean())\n",
    "print('P(whatsapp)         = %.4f' % whatsapp.mean())\n",
    "print('sumando los dos     = %.4f' % (mayorista.mean() + whatsapp.mean()))\n",
    "print('P(mayorista O whatsapp) = %.4f' % (mayorista | whatsapp).mean())\n",
    "print('lo que sobra        = %.4f' % (mayorista & whatsapp).mean())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Sumando sale 0,4897 y la verdad es 0,4327. Sobran exactamente 0,0570, que es\n",
    "la proporción de ventas que son **las dos cosas a la vez**: un\n",
    "mayorista que compró por WhatsApp.\n",
    "\n",
    "Al sumar las contaste dos veces. Por eso la regla es restar la\n",
    "intersección 🧮"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "P(A∪B)=P(A)+P(B)−P(A∩B)\n",
    "\n",
    "sumas las dos probabilidades y le restas lo que contaste dos veces"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Regla 2: la condicional, que es la que se usa de verdad"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\"Dado que ya sé algo, ¿qué probabilidad hay de lo otro\". En pandas esto es\n",
    "simplemente filtrar antes de promediar:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "P(A∣B)=P(A∩B)P(B)\n",
    "\n",
    "de todo lo que cumple B, qué parte cumple también A"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print('P(compra)                = %.4f' % v['compro'].mean())\n",
    "print('P(compra | mayorista)    = %.4f' % v.loc[mayorista, 'compro'].mean())\n",
    "print('P(compra | whatsapp)     = %.4f' % v.loc[whatsapp, 'compro'].mean())\n",
    "print('P(compra | marketplace)  = %.4f'\n",
    "      % v.loc[v['canal'] == 'Marketplace', 'compro'].mean())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Saber quién es el cliente **cambia** la probabilidad: de 0,5777\n",
    "sube a 0,7240 si es mayorista y baja a 0,4613 si viene por Marketplace 📈\n",
    "\n",
    "Y eso es, literalmente, de qué va el análisis de datos: buscar el dato que,\n",
    "al conocerlo, cambia lo que esperas 🔮"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Regla 3: independencia"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Dos cosas son independientes si saber una no te dice nada de la otra. La\n",
    "prueba es esta: si son independientes, la probabilidad de que pasen las dos es\n",
    "el producto de las dos por separado.\n",
    "\n",
    "Probemos con ciudad, que llevamos seis capítulos sospechando que no sirve\n",
    "para nada:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "for c in ['lima', 'arequipa', 'trujillo']:\n",
    "    es_ciudad = v['ciudad'] == c\n",
    "    juntas = (es_ciudad & (v['compro'] == 1)).mean()\n",
    "    producto = es_ciudad.mean() * v['compro'].mean()\n",
    "    print('%-9s juntas %.4f | producto %.4f | diferencia %+.4f'\n",
    "          % (c, juntas, producto, juntas - producto))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Prácticamente idénticas. **Ciudad y compra son independientes**:\n",
    "saber de qué ciudad es una venta no te dice nada sobre si se va a cerrar ✅\n",
    "\n",
    "Y ahora el contraste, con segmento:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "juntas = (mayorista & (v['compro'] == 1)).mean()\n",
    "producto = mayorista.mean() * v['compro'].mean()\n",
    "\n",
    "print('juntas   %.4f' % juntas)\n",
    "print('producto %.4f' % producto)\n",
    "print('la realidad es %.1f%% mayor de lo que serIa si fueran independientes'\n",
    "      % (100 * (juntas / producto - 1)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Un 25,3% por encima. Aquí no hay independencia ninguna: ser mayorista y\n",
    "comprar van juntos 🤝\n",
    "\n",
    "Guarda este cálculo porque es exactamente el que hace la prueba ji cuadrado\n",
    "del capítulo 13. Lo único que añade la prueba es decirte cuánta diferencia hace\n",
    "falta para que no sea casualidad."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## El error que cuesta campañas"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Este es el importante del capítulo, y lo he visto en presentaciones de\n",
    "verdad 😖"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print('P(compra | mayorista) = %.4f' % v.loc[mayorista, 'compro'].mean())\n",
    "print('P(mayorista | compra) = %.4f'\n",
    "      % (v.loc[v['compro'] == 1, 'segmento'] == 'Mayorista').mean())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "0,7240 y 0,3133. **Son dos números completamente distintos**, y\n",
    "en castellano se parecen tanto que se confunden todo el rato:\n",
    "\n",
    "- ✅ \"El **72,40%** de los mayoristas compra\". Verdad.\n",
    "\n",
    "- ✅ \"El **31,33%** de los que compran son mayoristas\". Verdad.\n",
    "\n",
    "- ❌ \"El 72,40% de los que compran son mayoristas\". Falso, y es lo que la\n",
    "gente entiende.\n",
    "\n",
    "Y la consecuencia es de plata. Si crees que el 72% de tus compradores son\n",
    "mayoristas, concentras el equipo comercial ahí y abandonas a los demás. Pero\n",
    "resulta que **casi siete de cada diez ventas cerradas vienen de otros\n",
    "segmentos** 💸\n",
    "\n",
    "La regla mnemotécnica: *P(A dado B) no es P(B dado A)*. Cuando leas un\n",
    "porcentaje, pregúntate siempre **sobre qué total está calculado**."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Bayes, que es la fórmula para darle la vuelta"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "El teorema de Bayes es justo eso: cómo pasar de una a la otra sin\n",
    "equivocarse."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "P(A∣B)=P(B∣A)P(A)P(B)\n",
    "\n",
    "para darle la vuelta a una condicional multiplicas por la tasa base y divides por la del otro suceso"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Vamos a comprobar que funciona:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "p_may = mayorista.mean()\n",
    "p_compra = v['compro'].mean()\n",
    "p_compra_dado_may = v.loc[mayorista, 'compro'].mean()\n",
    "\n",
    "bayes = p_compra_dado_may * p_may / p_compra\n",
    "\n",
    "print('con Bayes:  %.4f' % bayes)\n",
    "print('contando:   %.4f'\n",
    "      % (v.loc[v['compro'] == 1, 'segmento'] == 'Mayorista').mean())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Clavado 🎯\n",
    "\n",
    "Fíjate en la pieza que hace todo el trabajo: **P(A), la proporción de\n",
    "mayoristas**, que es 0,25. Como solo una de cada cuatro ventas es de un\n",
    "mayorista, por muy alta que sea su tasa de compra no pueden ser la mayoría de\n",
    "los cierres.\n",
    "\n",
    "A esa P(A) se le llama **tasa base**, y olvidarla es el error más\n",
    "famoso de toda la probabilidad."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## La tasa base, con las 21 negativas"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Imagina que alguien de sistemas te ofrece un detector de ventas rotas. Dice\n",
    "que acierta el 99%: si la venta está rota la detecta el 99% de las veces, y si\n",
    "está bien solo se equivoca el 1%.\n",
    "\n",
    "Suena excelente. Vamos a ver qué pasa cuando lo sueltas sobre estas ventas,\n",
    "donde ya sabemos que hay 21 rotas de 3.000:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "tasa_base = (v['monto'] < 0).mean()\n",
    "sensibilidad = 0.99\n",
    "falsa_alarma = 0.01\n",
    "\n",
    "alarmas_buenas = sensibilidad * tasa_base\n",
    "alarmas_falsas = falsa_alarma * (1 - tasa_base)\n",
    "\n",
    "print('proporcion de ventas rotas: %.5f' % tasa_base)\n",
    "print('alarmas correctas por venta: %.5f' % alarmas_buenas)\n",
    "print('alarmas falsas por venta:    %.5f' % alarmas_falsas)\n",
    "print()\n",
    "print('P(rota | suena la alarma) = %.4f'\n",
    "      % (alarmas_buenas / (alarmas_buenas + alarmas_falsas)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**El 41,10%.** O sea que cuando el detector del 99% suena, se\n",
    "equivoca más veces de las que acierta 😵\n",
    "\n",
    "Y no es que el detector sea malo: es buenísimo. El problema es que hay 2.979\n",
    "ventas sanas y solo 21 rotas. El 1% de errores sobre 2.979 son 29,79 alarmas\n",
    "falsas, más que las 20,79 correctas que salen del 99% sobre 21.\n",
    "\n",
    "Esto es lo que pasa con todos los detectores de cosas raras: fraude,\n",
    "enfermedades poco frecuentes, fallos de máquina. **Cuando lo que buscas es\n",
    "raro, la mayoría de las alarmas son falsas aunque el detector sea\n",
    "buenísimo** 🚨\n",
    "\n",
    "Es también la razón por la que el libro de machine learning tiene un capítulo\n",
    "entero sobre [clases\n",
    "raras](https://missyera.com/guias/machine-learning-desde-cero/clases-raras/): el mismo problema, con modelos."
   ]
  },
  {
   "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",
    "    v.groupby('segmento')['compro'].mean()['Mayoristas']\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",
    "KeyError: 'Mayoristas'\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Una ese de más 🤦 En el archivo el segmento se llama `Mayorista`,\n",
    "en singular.\n",
    "\n",
    "Parece tonto, y lo pongo aquí porque este error tiene una versión hermana que\n",
    "**no** da error y que es de las que más daño hacen:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print('mal escrito:  %.4f' % v.loc[v['segmento'] == 'Mayoristas', 'compro'].mean())\n",
    "print('bien escrito: %.4f' % v.loc[v['segmento'] == 'Mayorista', 'compro'].mean())\n",
    "print('cuantas filas trae el mal escrito:',\n",
    "      (v['segmento'] == 'Mayoristas').sum())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Con `groupby` te avisa. Con un filtro, **no**: te\n",
    "devuelve cero filas y un `nan`, tan tranquilo 😶\n",
    "\n",
    "Y si en vez de una media hubieras pedido un `sum()`, te habría\n",
    "devuelto 0,0, que parece un número de verdad y se cuela en cualquier informe.\n",
    "\n",
    "La defensa es la de siempre y cuesta un segundo: después de filtrar,\n",
    "**mira cuántas filas quedaron**."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Y dos más, y los dos son la regla número uno"
   ]
  },
  {
   "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",
    "    np.random.default_rng(7).choice(['si', 'no'], p=[0.7, 0.5])\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: Probabilities do not sum to 1. See Notes section of docstring for more information.\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ahí está el axioma en un mensaje de error: **las probabilidades de todo lo que puede pasar suman 1**. Un 70% y un 50% suman 120%, y no hay mundo donde eso signifique algo."
   ]
  },
  {
   "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",
    "    np.random.default_rng(7).binomial(10, 1.3)\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: p < 0, p > 1 or p is NaN\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Y el otro lado de lo mismo: una probabilidad sola tampoco puede pasar de 1. Suele salir de haber guardado un porcentaje sin dividir entre cien, que es de los descuidos más caros que hay porque a veces no revienta y te deja el número mal 🎲"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Practica 💪"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1. La probabilidad de compra por canal, ordenada\n",
    "\n",
    "Calcula P(compra | canal) para los cuatro canales y\n",
    "ordénalos. ¿Cuánto separa al mejor del peor?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 1\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. Un test de independencia casero\n",
    "\n",
    "Escribe algo que, dada una columna categórica, te diga\n",
    "cuánto se aleja de la independencia respecto a `compro`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 2\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3. Dale la vuelta tú\n",
    "\n",
    "Sabemos que P(compra | WhatsApp) es 0,6551. Calcula\n",
    "P(WhatsApp | compra) con Bayes y compruébalo contando."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 3\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4. Un detector con datos de verdad\n",
    "\n",
    "Usa la satisfacción baja (1 o 2) como alarma de \"esta\n",
    "venta no se va a cerrar\" y calcula si sirve."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 4\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 5. Fabrica dos cosas independientes\n",
    "\n",
    "Añade una columna con un número al azar y comprueba que es\n",
    "independiente de la compra. Sirve para ver qué pinta tiene la independencia de\n",
    "verdad."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 5\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 6. Probabilidad de dos filtros a la vez\n",
    "\n",
    "¿Qué probabilidad hay de que una venta sea de un mayorista\n",
    "Y venga por WhatsApp Y se cierre? Calcúlalo directo y con la cadena de\n",
    "condicionales."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 6\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 7. La probabilidad de cerrar, por segmento\n",
    "\n",
    "Calcula qué porcentaje cierra en cada segmento y ordénalos."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 7\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 8. ¿Son independientes el canal y el cierre?\n",
    "\n",
    "Comprueba si P(Web y cierra) es igual a P(Web) por P(cierra)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 8\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Dos porcentajes del mismo canal que no dicen lo mismo"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Antes de cerrar, la trampa. Los dos números están bien calculados y la conclusión que sale de mezclarlos está muy mal 🔀"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### La trampa\n",
    "\n",
    "Quieres saber cuántos mayoristas van a comprar el mes que viene. Tienes las dos probabilidades por separado, así que las multiplicas.\n",
    "\n",
    "```\n",
    "p_compra   = (v['compro'] == 1).mean()          # 0.5777\n",
    "p_mayor    = (v['segmento'] == 'Mayorista').mean()  # 0.2500\n",
    "\n",
    "print(round(p_compra * p_mayor * 3000))\n",
    "# 433\n",
    "\n",
    "real = ((v['compro'] == 1) &\n",
    "        (v['segmento'] == 'Mayorista')).mean()\n",
    "print(round(real * 3000))\n",
    "# 543\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",
    "El 72,40% de los mayoristas compra. ¿Qué porcentaje de las compras son de mayoristas?\n",
    "\n",
    "a) El 31,33%, porque los mayoristas son solo una cuarta parte de las ventas\n",
    "\n",
    "b) También el 72,40%\n",
    "\n",
    "c) No se puede saber con esa información\n",
    "\n",
    "d) Más del 72,40%, porque compran más"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Lo que te llevas"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 🎲 Una probabilidad es la proporción de veces que pasa algo, o sea la media\n",
    "de una columna de ceros y unos.\n",
    "\n",
    "- ➕ P(A o B) no es P(A) + P(B). Hay que restar lo que se cuenta dos veces:\n",
    "aquí 0,4897 contra 0,4327 de verdad.\n",
    "\n",
    "- 🔍 La condicional es filtrar antes de promediar. P(compra) es 0,5777 y\n",
    "P(compra|mayorista) es 0,7240.\n",
    "\n",
    "- 🔀 **P(A|B) no es P(B|A).** El 72,40% de los mayoristas compra,\n",
    "pero solo el 31,33% de las compras son de mayoristas.\n",
    "\n",
    "- ⚖️ Bayes es la fórmula para darle la vuelta, y la pieza que manda es la tasa\n",
    "base.\n",
    "\n",
    "- 🚨 Un detector con 99% de acierto sobre algo que pasa el 0,70% de las veces\n",
    "acierta el 41,11% de sus alarmas.\n",
    "\n",
    "- 👻 Un filtro mal escrito no da error: devuelve cero filas y un\n",
    "`nan`. Cuenta las filas después de filtrar.\n",
    "\n",
    "Y si de todo el capítulo te llevas una sola frase, que sea esta:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Todo porcentaje contesta a un \"dado qué\". Si no sabes cuál, no sabes qué\n",
    "te están diciendo."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Y esto de darle la vuelta a una condicional es exactamente lo que hace que\n",
    "un modelo con 99% de acierto sea inútil en un problema raro. Está contado 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": [
    "En el capítulo 8 vemos las tres distribuciones que de verdad se usan\n",
    "(binomial, Poisson y normal) y el teorema que explica por qué la campana aparece\n",
    "por todas partes aunque tus datos no sean campana 🔔"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Preguntas frecuentes"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "¿Qué es el teorema de Bayes?La regla que te deja dar vuelta una probabilidad condicional: si sabes la probabilidad de B dado A, te da la de A dado B. Es cómo se pasa de \"el test da positivo cuando hay enfermedad\" a lo que de verdad quieres saber, que es \"hay enfermedad cuando el test da positivo\".\n",
    "\n",
    "¿Cuál es la fórmula del teorema de Bayes?La probabilidad de A dado B es igual a la probabilidad de B dado A, por la probabilidad de A, dividido entre la probabilidad de B.\n",
    "\n",
    "¿Un ejemplo del teorema de Bayes?Un test que acierta el 99% suena infalible hasta que la enfermedad la tiene una persona de cada diez mil. Ahí la mayoría de los positivos son falsos, y el teorema es lo que lo demuestra con números. Está resuelto en este capítulo.\n",
    "\n",
    "¿Qué es la probabilidad condicional?La probabilidad de algo cuando ya sabes que pasó otra cosa. Cambia el resultado más de lo que la intuición espera, y es la pieza que necesita Bayes.\n",
    "\n",
    "¿Cómo se calcula la probabilidad condicional?Se divide la probabilidad de que pasen las dos cosas entre la probabilidad de la que ya sabes que pasó. Dicho fácil: te quedas solo con los casos donde pasó la primera y cuentas dentro de esos.\n",
    "\n",
    "¿Qué es el teorema de la probabilidad total?La forma de calcular la probabilidad de algo sumando por partes: se parte el mundo en casos que no se pisan, se calcula dentro de cada uno y se suma pesando por lo que pesa cada caso. Es el denominador de Bayes.\n",
    "\n",
    "¿Cuáles son las fórmulas de probabilidad que hacen falta?Tres: la de la unión, la de la intersección y la condicional. Con esas tres y el teorema de Bayes está cubierto casi todo lo que un analista necesita."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "Ese era el capítulo 7 de **Estadística desde cero**. El texto completo, con las salidas de cada bloque, está en https://missyera.com/guias/estadistica-desde-cero/probabilidad/\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
}
