{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# El titular dice lo que encontraste, no lo que hiciste\n",
    "\n",
    "Los mismos números dan cuatro titulares distintos. Cuál eliges decide si te aprueban el proyecto o te hacen volver con más datos.\n",
    "\n",
    "Cuaderno de soluciones del capítulo 19 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/el-titular-va-primero/\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": [
    "Hiciste el análisis. Los números están bien, la prueba es la que tocaba y el\n",
    "cuaderno corre de arriba abajo.\n",
    "\n",
    "Y ahora tienes que decirlo en una frase, porque nadie va a leer tu cuaderno.\n",
    "Esa frase es el trabajo entero visto desde afuera, y casi nunca se enseña 🌸"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Los números que vamos a contar"
   ]
  },
  {
   "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",
    "df = pd.read_csv(URL)\n",
    "df['monto'] = pd.to_numeric(df['monto'], errors='coerce')\n",
    "d = df[['canal', 'compro', 'segmento', 'monto']].dropna(subset=['canal', 'compro'])\n",
    "\n",
    "w = d[d['canal'] == 'WhatsApp']['compro']\n",
    "b = d[d['canal'] == 'Web']['compro']\n",
    "\n",
    "print('WhatsApp: n =', len(w), '| convierte', round(float(w.mean()), 4))\n",
    "print('Web     : n =', len(b), '| convierte', round(float(b.mean()), 4))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Dos canales, la conversión de cada uno. De ahí en adelante todo es la misma\n",
    "información contada de maneras distintas."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Titular 1: el relativo, que es el que todos usan"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "dif = float(w.mean() - b.mean())\n",
    "print('sube un', round(dif / float(b.mean()) * 100, 1), '%')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*\"WhatsApp convierte un 11,9% más que la web.\"*\n",
    "\n",
    "Suena bien y es cierto. Y tiene dos trampas que no se ven.\n",
    "\n",
    "La primera: es un **porcentaje de un porcentaje**. La conversión\n",
    "pasó de 58,3% a 65,2%, y eso es un 11,9% más *de lo que ya había*. Quien\n",
    "lo escuche sin pensar va a entender \"sube 11,9 puntos\", que es casi el doble de\n",
    "lo que pasó.\n",
    "\n",
    "La segunda es peor, y se ve mirando un segmento chico:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "bodega = d[d['segmento'] == 'Bodega']\n",
    "a2 = bodega[bodega['canal'] == 'WhatsApp']['compro']\n",
    "b2 = bodega[bodega['canal'] == 'Web']['compro']\n",
    "print('Bodega WhatsApp:', round(float(a2.mean()), 4))\n",
    "print('Bodega Web     :', round(float(b2.mean()), 4))\n",
    "print('relativo       :', round((float(a2.mean()) - float(b2.mean()))\n",
    "                                / float(b2.mean()) * 100, 1), '%')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "16,2% en Bodega contra 11,9% general. ¿Bodega es el mejor segmento?\n",
    "\n",
    "No necesariamente: el relativo **crece solo cuando la base es más\n",
    "chica**. Bodega convierte peor de entrada, así que la misma cantidad de\n",
    "puntos parece más. Con una base del 1%, subir un punto es un 100% de mejora, y\n",
    "sigue siendo un punto 🙃"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Titular 2: el absoluto, que es el honesto"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print('sube', round(dif * 100, 1), 'puntos')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*\"WhatsApp convierte 6,9 puntos más que la web.\"*\n",
    "\n",
    "Menos vistoso, imposible de malinterpretar. Y fíjate en la palabra\n",
    "**puntos**, que no es un adorno: decir \"6,9 por ciento más\" sería\n",
    "mentira, porque el por ciento ya está ocupado por la conversión.\n",
    "\n",
    "Esa distinción entre *puntos porcentuales* y *por ciento* es la\n",
    "que más se confunde en informes reales, y la que más discusiones caras\n",
    "provoca."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Titular 3: el intervalo, que es el que aguanta preguntas"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "se = float(np.sqrt(w.var(ddof=1) / len(w) + b.var(ddof=1) / len(b)))\n",
    "lo, hi = dif - 1.96 * se, dif + 1.96 * se\n",
    "print('entre', round(lo * 100, 1), 'y', round(hi * 100, 1), 'puntos')\n",
    "print('valor p:', round(float(stats.ttest_ind(w, b, equal_var=False)[1]), 4))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*\"WhatsApp convierte entre 2 y 12 puntos más.\"*\n",
    "\n",
    "Este es el bueno, y es el que casi nadie pone en el titular porque parece que\n",
    "te estás lavando las manos.\n",
    "\n",
    "Es al revés. Mira lo que hace en una reunión: si alguien te pregunta \"¿y qué\n",
    "tan seguro estás?\", ya lo contestaste. Y si el plan de la empresa necesitaba 10\n",
    "puntos para salir a cuenta, el intervalo te está diciendo que **puede que\n",
    "no alcance**, y eso es exactamente lo que esa persona necesita saber\n",
    "antes de firmar.\n",
    "\n",
    "El valor p dice que la diferencia es real. El intervalo dice\n",
    "**de qué tamaño**. En una reunión el segundo importa más, y lo\n",
    "trabajamos en el capítulo 10."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Titular 4: la plata, que es el que consigue el presupuesto"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "ticket = float(d['monto'].dropna().mean())\n",
    "print('ticket medio:', round(ticket, 2))\n",
    "for n in (1000, 10000):\n",
    "    print(' con', n, 'clientes ->', round(dif * n, 1), 'ventas mas,',\n",
    "          round(dif * n * ticket), 'soles')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*\"Con 1.000 clientes son unas 69 ventas más, cerca de 56.000 soles.\"*\n",
    "\n",
    "Este es el que hace que alguien deje de mirar el teléfono 💰\n",
    "\n",
    "Y también el más fácil de inflar. Tres cosas que hay que decir en voz alta al\n",
    "darlo:\n",
    "\n",
    "- **De dónde sale el 1.000.** Si te lo inventaste para que el\n",
    "número quede bonito, se nota en la primera pregunta.\n",
    "\n",
    "- **Que el ticket medio es un promedio**, con toda la dispersión\n",
    "que trabajamos en el capítulo 4 detrás.\n",
    "\n",
    "- **Que el rango también se traduce.** Con el borde bajo del\n",
    "intervalo, esos 56.000 se convierten en 17.000. Da menos gusto decirlo y es lo\n",
    "que te salva cuando alguien haga la cuenta."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## El titular que no sirve, y es el más común"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*\"Analizamos 3.037 ventas con una prueba t de Welch y obtuvimos un p-valor\n",
    "de 0,0053.\"*\n",
    "\n",
    "Eso es lo que **hiciste**, no lo que **encontraste**.\n",
    "Y es el titular de la mitad de los informes que me toca leer.\n",
    "\n",
    "Sale de un miedo razonable: si no digo el método, van a pensar que me lo\n",
    "inventé. Pero el método va en el cuerpo y en el anexo, donde quien quiera\n",
    "revisarlo lo encuentra. El titular es para quien tiene que decidir algo."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## La regla, en una línea"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Qué cambia, cuánto, con cuánta certeza y qué significa en tu\n",
    "negocio.**\n",
    "\n",
    "Los cuatro juntos caben en una frase:\n",
    "\n",
    "*\"Mover clientes a WhatsApp sube la conversión entre 2 y 12 puntos, o sea\n",
    "entre 17.000 y 95.000 soles al año con 1.000 clientes.\"*\n",
    "\n",
    "Eso es el análisis entero, dicho en el idioma de quien paga 🌟"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## El error de escribir el titular antes de mirar"
   ]
  },
  {
   "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",
    "    d['segmento'].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",
    "TypeError: Cannot perform reduction 'mean' with string dtype\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Parece un error tonto y es el síntoma de algo que no lo es: alguien quiso\n",
    "poner \"el segmento promedio\" en una lámina.\n",
    "\n",
    "No existe un segmento promedio. Lo que existe es el más frecuente, que es la\n",
    "moda del capítulo 3. Cuando un titular pide un\n",
    "número que no se puede calcular, casi siempre es porque la frase se escribió\n",
    "antes que el análisis."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Lo que te llevas"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- El titular dice qué encontraste, no qué hiciste.\n",
    "\n",
    "- El relativo exagera, y exagera más cuanto más chica es la base.\n",
    "\n",
    "- Puntos porcentuales y por ciento no son lo mismo.\n",
    "\n",
    "- El intervalo va en el titular, no en el anexo: contesta la pregunta antes\n",
    "de que te la hagan.\n",
    "\n",
    "- Traducir a dinero consigue presupuesto, y hay que traducir también el borde\n",
    "bajo.\n",
    "\n",
    "- Qué cambia, cuánto, con cuánta certeza y qué significa."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Comprueba que lo tienes\n",
    "\n",
    "Tienes una diferencia de 6,9 puntos con un intervalo que va de 2,1 a 11,8. ¿Cuál de estos titulares se sostiene si te preguntan?\n",
    "\n",
    "a) WhatsApp convierte entre 2 y 12 puntos más, y con 1.000 clientes son unos 56.000 soles\n",
    "\n",
    "b) WhatsApp convierte 11,9% más que Web\n",
    "\n",
    "c) WhatsApp es mejor canal que Web\n",
    "\n",
    "d) Analizamos 3.037 ventas con una prueba t de Welch\n",
    "\n",
    "---\n",
    "\n",
    "**La correcta es la a.**\n",
    "\n",
    "*b)* Es cierto y es el que más se usa, y esconde dos cosas: que es relativo sobre una base del 58%, y que el intervalo llega a bajar hasta 2 puntos.\n",
    "\n",
    "*c)* Mejor en conversión, con estos clientes y en este periodo. Sin el número y sin el intervalo, esa frase no se puede defender en una pregunta.\n",
    "\n",
    "*d)* Eso es lo que hiciste, no lo que encontraste. Es el titular que más aparece en informes reales y el que menos sirve.\n",
    "\n",
    "El titular que sobrevive es el que ya trae la incertidumbre y la consecuencia dentro 🌸"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Ejercicios"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1. El relativo crece cuando la base baja\n",
    "\n",
    "Comprueba que el mismo punto de mejora se ve distinto según\n",
    "de dónde partas."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "for base in (0.60, 0.30, 0.10, 0.02):\n",
    "    print('base', base, '-> subir 1 punto es un',\n",
    "          round(0.01 / base * 100, 1), '% de mejora')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "base 0.6 -> subir 1 punto es un 1.7 % de mejora\n",
    "base 0.3 -> subir 1 punto es un 3.3 % de mejora\n",
    "base 0.1 -> subir 1 punto es un 10.0 % de mejora\n",
    "base 0.02 -> subir 1 punto es un 50.0 % de mejora\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "El mismo punto, de 1,7% a 50%. Por eso cuando alguien te presuma un\n",
    "porcentaje de mejora enorme, la primera pregunta es \"¿sobre qué base?\". Y por eso\n",
    "cuando lo presumas tú, dilo antes de que te lo pregunten."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. Traduce el borde bajo, no solo el centro\n",
    "\n",
    "La cuenta que hay que llevar hecha a la reunión."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "ticket = float(d['monto'].dropna().mean())\n",
    "for etiqueta, efecto in (('borde bajo', lo), ('centro', dif), ('borde alto', hi)):\n",
    "    print(etiqueta.ljust(11), '->', round(efecto * 1000 * ticket), 'soles')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "borde bajo  -> 16733 soles\n",
    "centro      -> 56086 soles\n",
    "borde alto  -> 95439 soles\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "De 17.000 a 95.000. Ese rango es la respuesta honesta, y es la que quieres\n",
    "tener a mano cuando alguien te diga \"entonces contamos con 56.000\"."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3. El titular de tu compañero, revisado\n",
    "\n",
    "Comprueba si \"casi el doble\" se sostiene."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print('WhatsApp / Web =', round(float(w.mean()) / float(b.mean()), 3))\n",
    "print('WhatsApp - Web =', round(dif, 4))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "WhatsApp / Web = 1.119\n",
    "WhatsApp - Web = 0.0694\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "1,119 veces, no el doble. Cuando alguien diga \"casi el doble\", divide y mira:\n",
    "la mayoría de las veces esa frase sale de confundir el cociente con la\n",
    "diferencia, o de mirar un gráfico con el eje cortado, que es el truco que\n",
    "trabajo en [Gráficos que se\n",
    "entienden](https://missyera.com/guias/python-desde-cero/graficos/)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4. Cuánto se ensancha el titular si te falta muestra\n",
    "\n",
    "Ve recortando la muestra y mira el intervalo abrirse."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def intervalo(a, bb):\n",
    "    di = float(a.mean() - bb.mean())\n",
    "    s = float(np.sqrt(a.var(ddof=1) / len(a) + bb.var(ddof=1) / len(bb)))\n",
    "    return (di - 1.96 * s) * 100, (di + 1.96 * s) * 100\n",
    "\n",
    "for corte, nombre in ((1, 'entera'), (2, 'mitad'), (4, 'cuarto')):\n",
    "    mw = w.sample(len(w) // corte, random_state=0)\n",
    "    mb = b.sample(len(b) // corte, random_state=0)\n",
    "    a1, a2 = intervalo(mw, mb)\n",
    "    print(nombre.ljust(7), 'n =', len(mw) + len(mb),\n",
    "          '| entre', round(a1, 1), 'y', round(a2, 1),\n",
    "          '| ancho', round(a2 - a1, 1))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "entera  n = 1526 | entre 2.1 y 11.8 | ancho 9.7\n",
    "mitad   n = 762 | entre 2.5 y 16.2 | ancho 13.7\n",
    "cuarto  n = 381 | entre -1.1 y 18.1 | ancho 19.2\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Con la muestra entera el titular es \"sube entre 2 y 12 puntos\". Con un cuarto\n",
    "pasa a \"entre menos 1 y 18\", que cruza el cero: ya no puedes descartar que no\n",
    "haya diferencia.\n",
    "\n",
    "Los mismos datos y la misma dirección, y un titular que se convierte en \"no\n",
    "sabemos\". La muestra no es un detalle técnico del anexo: es lo que decide si\n",
    "tienes titular o no lo tienes. Cuánta hace falta se calcula antes, y está en el\n",
    "capítulo 18."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 5. Escribe las cuatro versiones de un tirón\n",
    "\n",
    "Una función para no volver a improvisar el titular."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def titulares(a, b, ticket, clientes=1000):\n",
    "    dif = float(a.mean() - b.mean())\n",
    "    se = float(np.sqrt(a.var(ddof=1) / len(a) + b.var(ddof=1) / len(b)))\n",
    "    return {\n",
    "        'relativo': str(round(dif / float(b.mean()) * 100, 1)) + '%',\n",
    "        'absoluto': str(round(dif * 100, 1)) + ' puntos',\n",
    "        'intervalo': str(round((dif - 1.96 * se) * 100, 1)) + ' a '\n",
    "                     + str(round((dif + 1.96 * se) * 100, 1)) + ' puntos',\n",
    "        'plata': str(round(dif * clientes * ticket)) + ' soles'}\n",
    "\n",
    "for clave, valor in titulares(w, b, ticket).items():\n",
    "    print(clave.ljust(10), valor)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "relativo   11.9%\n",
    "absoluto   6.9 puntos\n",
    "intervalo  2.1 a 11.8 puntos\n",
    "plata      56086 soles\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Guárdatela. Correrla en dos segundos y ver las cuatro juntas te obliga a\n",
    "elegir a propósito, en vez de escribir la primera que se te ocurra, que casi\n",
    "siempre es el relativo porque es la más grande."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 6. El titular con la limitación dentro\n",
    "\n",
    "Cuenta cuántos clientes distintos hay detrás de esas ventas."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sub = df[df['canal'].isin(['WhatsApp', 'Web'])]\n",
    "print('ventas  :', len(sub))\n",
    "print('clientes:', sub['cliente_id'].nunique())\n",
    "print('ventas por cliente:', round(len(sub) / sub['cliente_id'].nunique(), 2))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "ventas  : 1526\n",
    "clientes: 571\n",
    "ventas por cliente: 2.67\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "1.526 ventas de 571 clientes, o sea unas 2,7 por cabeza. Las filas\n",
    "**no son independientes**: si un cliente compra siempre, aporta tres\n",
    "filas que dicen lo mismo. Es el problema número cuatro del capítulo\n",
    "17, y hace que el intervalo real sea más ancho que el\n",
    "que calculamos.\n",
    "\n",
    "Dicho en el titular: \"entre 2 y 12 puntos, con la salvedad de que son 571\n",
    "clientes y no 1.526 independientes, así que el rango real es algo más ancho\". Es\n",
    "una frase incómoda y es la que hace que te crean la próxima vez 💛"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "Ese era el capítulo 19 de **Estadística desde cero**. El texto completo, con las salidas de cada bloque, está en https://missyera.com/guias/estadistica-desde-cero/el-titular-va-primero/\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
}
