{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# ¿Es real o es ruido?\n",
    "\n",
    "La pregunta que decide si una reunión de una hora tenía sentido, medida sobre las ventas de verdad.\n",
    "\n",
    "Cuaderno de soluciones del capítulo 1 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/es-real-o-es-ruido/\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": [
    "Hola! Bienvenida al libro 🌸\n",
    "\n",
    "Voy a empezar contándote una reunión que he visto muchísimas veces, en\n",
    "empresas grandes y chicas, y que siempre termina igual.\n",
    "\n",
    "Alguien proyecta una lámina: **\"las ventas subieron 3% este mes\"**.\n",
    "Y ahí arranca la hora. Que si fue la campaña, que si el nuevo vendedor, que si\n",
    "el clima. Se reparten felicitaciones, se decide repetir lo que sea que se hizo,\n",
    "y se agenda un seguimiento.\n",
    "\n",
    "Nadie hace la única pregunta que había que hacer: **¿cuánto se mueven\n",
    "las ventas normalmente?**\n",
    "\n",
    "Porque si las ventas se mueven 14% de un mes a otro sin que pase nada, ese\n",
    "3% no es un logro. Es el ruido de siempre disfrazado de noticia. Y la reunión\n",
    "entera, con las seis personas que estaban dentro, se acaba de ir a la basura 🗑️\n",
    "\n",
    "Eso es la estadística. No es la fórmula de la desviación estándar ni la tabla\n",
    "de la campana. Es esta pregunta:\n",
    "\n",
    "**¿Esta diferencia que estoy viendo es real, o es lo que varía normalmente?**\n",
    "\n",
    "Todo lo demás del libro son herramientas para contestarla.\n",
    "\n",
    "Y antes de arrancar, contéstate una: **¿cuándo fue la última vez que celebraste o sufriste por un número que se movió?** Guárdala, porque al terminar el capítulo vas a poder decir si aquello era real 📊"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Vamos a medirlo con datos de verdad"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "No te voy a pedir que me creas. Vamos a medir cuánto se mueven unas ventas\n",
    "reales, y de ahí sale si el 3% era noticia o no.\n",
    "\n",
    "Trabajamos con el mismo archivo de todos los libros: las ventas de una\n",
    "distribuidora peruana, con la suciedad puesta a propósito porque es la que te\n",
    "vas a encontrar 🧹"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "\n",
    "URL = 'https://missyera.com/static/datasets/ventas-miss-yera.csv'\n",
    "\n",
    "v = pd.read_csv(URL)\n",
    "print(v.shape)\n",
    "print(v[['fecha', 'monto']].head(3))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "3.037 ventas y 14 columnas. Se ve bien, ¿no? Pues mira lo que pasa cuando\n",
    "intento sacar el mes de cada venta."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## El primer golpe"
   ]
  },
  {
   "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['fecha'].dt.month\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",
    "AttributeError: Can only use .dt accessor with datetimelike values\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Tranqui, no rompiste nada 🙂 pandas te está diciendo algo importante:\n",
    "`fecha` no es una fecha. Es texto que *parece* fecha.\n",
    "\n",
    "El accesorio `.dt` (de *datetime*) es el que da acceso a\n",
    "año, mes, día y día de la semana. Solo funciona sobre columnas que pandas sabe\n",
    "que son fechas, y aquí leyó el CSV y lo dejó todo como texto porque nadie le\n",
    "dijo lo contrario.\n",
    "\n",
    "Lo mismo pasa con `monto`. Así que antes de calcular nada, se\n",
    "convierte:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "v['monto'] = pd.to_numeric(v['monto'].str.replace(',', '.'))\n",
    "\n",
    "iso = pd.to_datetime(v['fecha'], format='%Y-%m-%d', errors='coerce')\n",
    "resto = iso.isna()\n",
    "iso[resto] = pd.to_datetime(v.loc[resto, 'fecha'], format='%d/%m/%Y')\n",
    "v['fecha'] = iso\n",
    "\n",
    "print(v['fecha'].min().date(), v['fecha'].max().date())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Un año y medio de ventas, del 1 de enero de 2025 al 24 de junio de 2026.\n",
    "\n",
    "Eso de convertir en dos pasos es porque el archivo trae las fechas escritas\n",
    "de dos formas distintas, y lo vemos con calma en el capítulo 2. Por ahora\n",
    "quédate con que ya son fechas de verdad."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Cuánto se mueven las ventas"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ahora sí. Sumo lo vendido por mes:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "mes = v.groupby(v['fecha'].dt.to_period('M'))['monto'].sum()\n",
    "print(mes.round(0).head(6))\n",
    "print('meses:', len(mes))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Y ahora la parte que importa: cuánto cambia cada mes respecto al anterior.\n",
    "`pct_change()` hace exactamente eso 📈"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "cambio = (mes.pct_change() * 100).dropna()\n",
    "print(cambio.round(1).head(8))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Mírala bien un segundo, porque esta tabla ya contesta la pregunta de la\n",
    "reunión.\n",
    "\n",
    "Febrero subió **3,0%**. Ese es exactamente el número de la\n",
    "lámina. Y ahora mira los que vienen: abril bajó 18%, mayo subió 39%, agosto\n",
    "bajó 14,7%.\n",
    "\n",
    "El 3% de febrero, al lado de eso, no se distingue de nada."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## El número que había que llevar a la reunión"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print('media del cambio:      %.2f%%' % cambio.mean())\n",
    "print('media en valor absoluto: %.2f%%' % cambio.abs().mean())\n",
    "print('el peor mes:           %.2f%%' % cambio.min())\n",
    "print('el mejor mes:          %.2f%%' % cambio.max())\n",
    "print('meses que se movieron menos de 3%%: %d de %d'\n",
    "      % ((cambio.abs() < 3).sum(), len(cambio)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ahí está, y son cuatro líneas 👇\n",
    "\n",
    "- 📊 El mes promedio se mueve **14,41%** respecto al anterior.\n",
    "En valor absoluto, o sea sin importar si sube o baja.\n",
    "\n",
    "- ⚖️ La media del cambio con signo es **0,44%**. O sea que a lo\n",
    "largo del año y medio las subidas y las bajadas casi se cancelan: el negocio no\n",
    "está creciendo ni cayendo, está oscilando.\n",
    "\n",
    "- 🎢 El rango va de **-32,36%** a **+39,32%**.\n",
    "\n",
    "- 🎯 Solo **3 meses de 17** se movieron menos de 3%.\n",
    "\n",
    "Un 3% en este negocio es de los meses *más planos* que existen. Es\n",
    "literalmente lo contrario de una noticia.\n",
    "\n",
    "Fíjate en lo poco que hizo falta: agrupar por mes, sacar el cambio\n",
    "porcentual y mirar la media del valor absoluto. Eso ya salva una hora de\n",
    "reunión, y no hemos usado ni una fórmula todavía 💪"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## El atajo que se inventa medio año"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ahora te voy a enseñar el error, porque este me pareció grave de verdad\n",
    "cuando lo vi.\n",
    "\n",
    "Convertir las fechas en dos pasos es feo. Y pandas ofrece un atajo precioso\n",
    "que se ve muchísimo por ahí: `format='mixed'` le dice \"descúbrelo\n",
    "tú\", y `dayfirst=True` le dice \"en mi país el día va primero\".\n",
    "\n",
    "Parece exactamente lo que necesitamos. Míralo:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "atajo = pd.to_datetime(pd.read_csv(URL)['fecha'], format='mixed', dayfirst=True)\n",
    "print('meses con el atajo:', atajo.dt.to_period('M').nunique())\n",
    "print('meses de verdad:   ', v['fecha'].dt.to_period('M').nunique())\n",
    "print('fechas cambiadas:  ', (atajo != v['fecha']).sum())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Léelo otra vez 😳\n",
    "\n",
    "El atajo **no dio error**. No avisó. No puso un warning. Se\n",
    "llevó por delante **847 fechas** y se inventó **seis meses\n",
    "que no existen**.\n",
    "\n",
    "Lo que pasó es esto: `dayfirst=True` se aplica también a las\n",
    "fechas que ya venían bien escritas. Cuando le llega `2025-06-05`,\n",
    "que es el 5 de junio, ve que el día cabe en el hueco del mes y lo cambia de\n",
    "sitio: te devuelve el 6 de mayo. Solo se salvan las fechas donde el día es 13 o\n",
    "más, porque ahí no hay confusión posible.\n",
    "\n",
    "Y ahora piensa qué pasa con todo lo que hicimos antes. El análisis mensual,\n",
    "la estacionalidad, el \"cuánto se mueve el negocio\": todo calculado sobre meses\n",
    "inventados, sin un solo mensaje rojo en pantalla.\n",
    "\n",
    "**Los errores que no dan error son los que hacen daño.** Los que\n",
    "te tiran el programa los arreglas y ya. Estos llegan a una diapositiva 📉\n",
    "\n",
    "La forma de cazarlo es la de siempre: después de convertir fechas, mira el\n",
    "mínimo, el máximo y cuántos meses distintos hay. Si tu archivo cubre año y\n",
    "medio y salen 24 meses, algo se rompió."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Las dos mitades de la estadística"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Con eso ya se entiende la división del libro, que es sencilla:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "| Mitad | Qué contesta | Ejemplo de este capítulo |\n",
    "|---|---|---|\n",
    "| **Descriptiva** | Qué hay en los datos que tengo | El mes promedio se mueve 14,41% |\n",
    "| **Inferencial** | Qué puedo afirmar de lo que NO medí | ¿Ese 3% aguanta, o cae dentro del ruido? |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "La descriptiva es honesta y aburrida: describe lo que tienes y no promete\n",
    "nada más. La inferencial es la que da miedo y la que se usa mal, porque es la\n",
    "que se atreve a decir \"esto también pasa fuera de mi muestra\".\n",
    "\n",
    "Los capítulos 2 al 6 son descriptiva. Del 7 al 13, inferencia. Y el 14 son\n",
    "los errores que invalidan un análisis entero, que casi todos viven en la\n",
    "segunda mitad."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Señal y ruido, viéndolos de cerca"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Antes de cerrar quiero que veas los dos con los ojos, porque una vez que los\n",
    "distingues ya no se te olvida.\n",
    "\n",
    "La columna `compro` vale 1 si esa venta se cerró. Voy a mirar el\n",
    "porcentaje de cierre por ciudad:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print((v.groupby('ciudad')['compro'].mean() * 100).round(1))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Dos cosas 👀\n",
    "\n",
    "La primera, que te habrá saltado a la cara: hay **nueve ciudades donde\n",
    "debería haber seis**. Lima está escrita de cuatro formas distintas y para\n",
    "pandas son cuatro ciudades diferentes. Eso lo limpiamos en el capítulo 2, y es\n",
    "el motivo por el que la limpieza va antes que la estadística: no hay medida que\n",
    "sobreviva a datos sucios.\n",
    "\n",
    "La segunda, la que nos importa hoy: los números se parecen todos. Del 55,1%\n",
    "al 61,0%, y con las cuatro Limas mezcladas ahí dentro. Nada destaca.\n",
    "\n",
    "Ahora mira lo mismo por segmento de cliente:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print((v.groupby('segmento')['compro'].mean() * 100).round(1))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Esto ya es otra cosa 🔥\n",
    "\n",
    "Una bodega cierra el 37,6% y un mayorista el 72,3%. Casi el doble. Eso no se\n",
    "parece en nada a lo de ciudad.\n",
    "\n",
    "**Eso es señal.** Lo de ciudad es ruido. Y de momento lo estamos\n",
    "diciendo a ojo, que es exactamente lo que quiero que dejes de hacer: en el\n",
    "capítulo 13 le ponemos un número a cada uno y sale que la diferencia por ciudad\n",
    "tiene un valor p de 0,9813, o sea \"no hay nada aquí\", mientras que la de\n",
    "segmento sale con una probabilidad tan chica que hay que escribirla en notación\n",
    "científica.\n",
    "\n",
    "Pero fíjate en lo importante: **a ojo también se veía**. Los\n",
    "métodos del libro no están para descubrir lo que salta a la vista, sino para\n",
    "los casos dudosos, que son casi todos."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Y dos más que salen el primer día"
   ]
  },
  {
   "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['monto'].mean(axis=1)\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: No axis named 1 for object type Series\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Una columna sola es una **Serie** y no tiene dos dimensiones, así que no hay eje 1 al que promediar. El `axis=1` vale cuando promedias varias columnas de una tabla, y aquí solo hay una."
   ]
  },
  {
   "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('ciudad')['monto'].mean().sort_values(ascending='si')\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: For argument \"ascending\" expected type bool, received type str.\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Pandas quiere `True` o `False`, no la palabra. Parece una tontería y es el error que más veces vas a cometer en tu vida: las opciones de una función se escriben como la librería las pide, y las librerías están en inglés 🙃"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Practica 💪"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Los ejercicios son la mitad del libro. Intenta antes de abrir."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## El cien por ciento que salió de cinco filas"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Antes de los ejercicios, mira esto, porque es el error de este capítulo entero condensado en dos líneas de código 🎉"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### La trampa\n",
    "\n",
    "Buscas dónde está lo bueno. Partes por ciudad, segmento, canal y categoría, y aparecen grupos que convierten al 100%.\n",
    "\n",
    "```\n",
    "g = v.groupby(['ciudad', 'segmento', 'canal', 'categoria'])\n",
    "chicos = g['compro'].agg(['mean', 'count'])\n",
    "chicos = chicos[chicos['count'].between(3, 10)]\n",
    "\n",
    "print(len(chicos), (chicos['mean'] == 1).sum())\n",
    "# 429 40\n",
    "```\n",
    "\n",
    "**Qué está mal**\n",
    "\n",
    "Cuarenta grupos perfectos 🎉 Y todos tienen entre tres y diez ventas.\n",
    "\n",
    "Con cinco intentos, que salgan cinco compras pasa por pura suerte bastante a menudo. Lo que descubriste no es un segmento que convierte al 100%: es que si partes 3.000 filas en 429 pedacitos, algunos van a salir perfectos aunque no haya nada especial en ellos.\n",
    "\n",
    "Y esta es la trampa que le da título al capítulo, porque el número no está mal calculado. El 100% de ese grupo es cierto. Lo que es falso es la conclusión de que ahí hay algo.\n",
    "\n",
    "La costumbre que te ahorra la mitad de los sustos de este libro: **ningún porcentaje se mira sin el `count` al lado**. Con `.agg(['mean', 'count'])` te sale gratis, y a partir de ahí los grupos de cinco filas se ven solos."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Comprueba que lo tienes\n",
    "\n",
    "Las ventas de este mes subieron 3% y el mes promedio se mueve 14,41%. ¿Qué reportas?\n",
    "\n",
    "a) Que el mes entró dentro de lo normal, y digo cuánto es lo normal\n",
    "\n",
    "b) Que subieron 3%, que es un dato cierto\n",
    "\n",
    "c) Que hay una tendencia al alza que hay que sostener\n",
    "\n",
    "d) Que hay que investigar qué lo causó\n",
    "\n",
    "---\n",
    "\n",
    "**La correcta es la a.**\n",
    "\n",
    "*b)* Cierto sí es. Piensa en qué se va a hacer con esa frase en la reunión.\n",
    "\n",
    "*c)* Con un solo mes no se ve ninguna tendencia. ¿Cuántos meses de 17 se movieron menos de 3%?\n",
    "\n",
    "*d)* Investigar cuesta horas de gente. Antes de gastarlas, pregúntate si hay algo que explicar.\n",
    "\n",
    "Tres de 17 meses se movieron menos de 3%: ese 3% es de los meses más planos que hay."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1. Cuánto se mueven las unidades\n",
    "\n",
    "Hicimos el ejercicio con el monto. Hazlo con\n",
    "`unidades`: suma por mes, cambio porcentual y media en valor\n",
    "absoluto. ¿Se mueve más o menos que el dinero?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "u = v.groupby(v['fecha'].dt.to_period('M'))['unidades'].sum()\n",
    "cambio_u = (u.pct_change() * 100).dropna()\n",
    "print('unidades, media absoluta: %.2f%%' % cambio_u.abs().mean())\n",
    "print('monto, media absoluta:    %.2f%%' % cambio.abs().mean())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "unidades, media absoluta: 9.55%\n",
    "monto, media absoluta:    14.41%\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Las unidades se mueven bastante menos que el dinero: 9,55% contra 14,41%.\n",
    "\n",
    "Tiene sentido y vale la pena entender por qué. El monto de una venta depende\n",
    "de dos cosas que varían: cuántas unidades y a qué precio. Las unidades solo\n",
    "dependen de una. Cuando un número está hecho de dos números que bailan, baila\n",
    "más 💃\n",
    "\n",
    "Esto tiene una consecuencia práctica: si quieres detectar un cambio de\n",
    "verdad en el negocio, mirar unidades te da menos ruido de fondo que mirar\n",
    "soles."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. El mes más raro\n",
    "\n",
    "Encuentra el mes con la caída más fuerte y el de la subida\n",
    "más fuerte, con su nombre, no solo el número."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print('peor:  ', cambio.idxmin(), '%.2f%%' % cambio.min())\n",
    "print('mejor: ', cambio.idxmax(), '%.2f%%' % cambio.max())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "peor:   2026-06 -32.36%\n",
    "mejor:  2025-05 39.32%\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Y aquí hay trampa, mírala bien 🕵️\n",
    "\n",
    "El peor mes es junio de 2026, que es **el último mes del archivo**.\n",
    "Y arriba vimos que los datos terminan el 24 de junio. O sea que ese mes tiene\n",
    "24 días y los demás tienen 30 o 31.\n",
    "\n",
    "Esa caída del 32% no es una caída del negocio: es un mes al que le faltan\n",
    "seis días. Es de los errores más comunes que hay en informes de verdad, y no\n",
    "avisa de nada porque el cálculo está perfecto.\n",
    "\n",
    "La regla: **el último periodo de cualquier serie es sospechoso hasta\n",
    "que compruebes que está completo**. Se comprueba mirando el máximo de la\n",
    "fecha, como hicimos, y si está incompleto se saca del análisis o se anota al\n",
    "lado."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3. Las cuentas sin el mes incompleto\n",
    "\n",
    "Repite la medición de la variación quitando el último mes.\n",
    "¿Cambia la conclusión sobre el 3%?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "completos = mes.iloc[:-1]\n",
    "c2 = (completos.pct_change() * 100).dropna()\n",
    "print('con el mes cojo:  %.2f%%' % cambio.abs().mean())\n",
    "print('sin el mes cojo:  %.2f%%' % c2.abs().mean())\n",
    "print('peor mes ahora:   %.2f%%' % c2.min())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "con el mes cojo:  14.41%\n",
    "sin el mes cojo:  13.29%\n",
    "peor mes ahora:   -23.09%\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "La media baja de 14,41% a 13,29% y el peor mes pasa de -32,36% a -23,09%.\n",
    "\n",
    "O sea que sí, el mes incompleto estaba exagerando la variación. Pero la\n",
    "conclusión no se mueve ni un milímetro: **13,29% sigue siendo más de\n",
    "cuatro veces el 3% de la lámina**.\n",
    "\n",
    "Esto pasa a menudo y conviene tenerlo claro: encontrar un error no siempre\n",
    "cambia la respuesta. Se corrige igual, porque la próxima vez sí la cambiará."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4. ¿Y si el mes hubiera subido 12%?\n",
    "\n",
    "Con lo medido, ¿a partir de qué subida empezarías a\n",
    "prestar atención? Escribe tu criterio con un número antes de mirar."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "\n",
    "for umbral in [3, 10, 15, 20, 30]:\n",
    "    cuantos = (cambio.abs() >= umbral).sum()\n",
    "    print('%2d%% o mas: %2d de %d meses (%.0f%%)'\n",
    "          % (umbral, cuantos, len(cambio), 100 * cuantos / len(cambio)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    " 3% o mas: 14 de 17 meses (82%)\n",
    "10% o mas:  9 de 17 meses (53%)\n",
    "15% o mas:  7 de 17 meses (41%)\n",
    "20% o mas:  5 de 17 meses (29%)\n",
    "30% o mas:  3 de 17 meses (18%)\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ahora se puede hablar con números en vez de con sensaciones 🙌\n",
    "\n",
    "Una subida del 3% o más pasa en el 82% de los meses. O sea que celebrarla es\n",
    "celebrar casi cualquier mes.\n",
    "\n",
    "Un movimiento del 30% o más pasa solo en el 18% de los meses. Ahí ya tienes un\n",
    "criterio defendible y que puedes escribir antes de mirar el dato: *me llama\n",
    "la atención lo que pasa en menos de uno de cada cinco meses*.\n",
    "\n",
    "Guárdate esa idea porque es la del libro entero. Ese 18% del final es, en\n",
    "espíritu, lo mismo que un valor p: la probabilidad de ver algo así de grande si\n",
    "no está pasando nada especial. Lo formalizamos en el capítulo 12, pero el\n",
    "concepto es este y ya lo acabas de calcular tú 😍"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 5. La trampa de comparar contra el mejor mes\n",
    "\n",
    "Alguien compara septiembre contra agosto y sale un +16%.\n",
    "Otro compara septiembre contra mayo. Calcula las dos y explica por qué la\n",
    "segunda es tramposa."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print('sep vs ago: %+.1f%%' % (100 * (mes['2025-09'] / mes['2025-08'] - 1)))\n",
    "print('sep vs may: %+.1f%%' % (100 * (mes['2025-09'] / mes['2025-05'] - 1)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "sep vs ago: +16.0%\n",
    "sep vs may: -11.6%\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "El mismo mes de septiembre sube 16,0% o baja 11,6% según con quién lo\n",
    "compares 🤯\n",
    "\n",
    "No hay ningún error de cálculo en ninguna de las dos. Las dos son ciertas. Y\n",
    "por eso mismo esto es tan peligroso: quien elige la base elige el titular.\n",
    "\n",
    "Agosto fue un mes flojo (había caído 14,7%), así que compararse contra él\n",
    "regala una subida. Mayo fue el mejor mes del año, así que compararse contra él\n",
    "regala una caída.\n",
    "\n",
    "La defensa es fijar la comparación **antes** de mirar el\n",
    "resultado. Mes contra mes anterior, o mes contra el mismo mes del año pasado.\n",
    "Lo que no vale es elegir la base después de ver cuál queda mejor, que tiene\n",
    "nombre y sale en el capítulo 17: se llama *p-hacking* cuando se hace con\n",
    "pruebas, y es la misma familia de trampa."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 6. Encuentra otra columna que sea puro ruido\n",
    "\n",
    "Vimos que ciudad no separa nada y segmento sí. Prueba con\n",
    "`canal` y con `categoria`. ¿Cuál de las dos se parece más\n",
    "a ciudad?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "for col in ['canal', 'categoria']:\n",
    "    tasa = (v.groupby(col)['compro'].mean() * 100).round(1)\n",
    "    print(col, '-> de %.1f a %.1f  (brecha %.1f puntos)'\n",
    "          % (tasa.min(), tasa.max(), tasa.max() - tasa.min()))\n",
    "    print(tasa.to_string())\n",
    "    print()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "canal -> de 46.1 a 65.2  (brecha 19.1 puntos)\n",
    "canal\n",
    "Marketplace    46.1\n",
    "Tienda         61.9\n",
    "Web            58.3\n",
    "WhatsApp       65.2\n",
    "\n",
    "categoria -> de 55.8 a 59.0  (brecha 3.2 puntos)\n",
    "categoria\n",
    "Abarrotes           59.0\n",
    "Bebidas             57.5\n",
    "Cuidado personal    55.8\n",
    "Limpieza            58.9\n",
    "Snacks              57.4\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`categoria` es la que se parece a ciudad: **3,2 puntos**\n",
    "entre la categoría que más cierra y la que menos, o sea nada.\n",
    "\n",
    "`canal` no: **19,1 puntos**. Marketplace cierra el\n",
    "46,1% y WhatsApp el 65,2%. Eso es señal, aunque menos escandalosa que la de\n",
    "segmento.\n",
    "\n",
    "Y aquí quiero que te quedes con el matiz que hace falta todo el libro:\n",
    "**una brecha de 3,2 puntos podría ser real si hubiera muchísimos más\n",
    "datos**. Lo que hace que sea ruido aquí no es el 3,2, es el 3,2\n",
    "*con 3.037 filas repartidas en cinco categorías*. Con 300.000 filas, esa\n",
    "misma brecha sería una diferencia sólida.\n",
    "\n",
    "El tamaño de la diferencia solo significa algo cuando lo miras junto a\n",
    "cuántos datos tienes. Esa idea es la mitad del libro, y la ponemos en fórmula en\n",
    "el capítulo 10."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 7. ¿Qué columna separa de verdad?\n",
    "\n",
    "Repite la comparación con las cuatro columnas categóricas y ordénalas por cuánto separan."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "for col in ['ciudad', 'segmento', 'canal', 'categoria']:\n",
    "    t = v.groupby(col)['monto'].mean()\n",
    "    print('%-11s va de %7.2f a %7.2f, o sea %5.2f veces'\n",
    "          % (col, t.min(), t.max(), t.max() / t.min()))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "ciudad      va de  724.22 a  960.98, o sea  1.33 veces\n",
    "segmento    va de  178.72 a 1851.88, o sea 10.36 veces\n",
    "canal       va de  789.69 a  810.90, o sea  1.03 veces\n",
    "categoria   va de  746.69 a  835.12, o sea  1.12 veces\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Una de las cuatro no se parece a las otras 😳\n",
    "\n",
    "**Segmento separa diez veces y las demás no llegan a una y media.** Y eso decide el libro entero: cuando alguien te pida \"analiza las ventas\", esta tabla de cuatro líneas te dice por dónde empezar antes de haber hecho ninguna prueba.\n",
    "\n",
    "Guárdate esta idea, que vuelve en el capítulo 9: una columna que separa mucho es justo la que hay que respetar al sacar una muestra 🔑"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 8. Lo mismo, pero con sesenta filas\n",
    "\n",
    "Calcula el promedio del monto con todas las filas y después con cinco muestras de sesenta."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print('con las %d filas de golpe: %.2f' % (len(v), v['monto'].mean()))\n",
    "for semilla in range(5):\n",
    "    print('  con 60 al azar:        %.2f'\n",
    "          % v.sample(60, random_state=semilla)['monto'].mean())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "con las 3037 filas de golpe: 801.66\n",
    "  con 60 al azar:        678.27\n",
    "  con 60 al azar:        721.79\n",
    "  con 60 al azar:        919.94\n",
    "  con 60 al azar:        794.49\n",
    "  con 60 al azar:        741.76\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "De 678 a 920 según a quién le tocó 🎲\n",
    "\n",
    "Ese vaivén de casi 250 soles no es que los datos estén mal: es lo que hace una muestra chica. Y es exactamente lo que el capítulo 10 va a aprender a poner en números, en vez de mirarlo y encogerse de hombros.\n",
    "\n",
    "La pregunta que quiero que te lleves: si te enseñan un promedio, **¿sabes con cuántas filas se calculó?** 🙋‍♀️"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Lo que te llevas"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- ❓ La estadística contesta una sola pregunta: ¿es real o es ruido? Todo lo\n",
    "demás es herramienta.\n",
    "\n",
    "- 📏 Antes de celebrar una diferencia, mide cuánto se mueven las cosas\n",
    "normalmente. Aquí el mes promedio se mueve 14,41%, así que un 3% es de los\n",
    "meses más planos que hay.\n",
    "\n",
    "- 🕳️ Los errores que no dan error son los peores. El atajo\n",
    "`dayfirst=True` cambió 847 fechas e inventó seis meses sin avisar.\n",
    "\n",
    "- 📅 El último periodo de una serie es sospechoso hasta que compruebes que\n",
    "está completo. Aquí junio tenía 24 días y fingía una caída del 32%.\n",
    "\n",
    "- 🎯 Quien elige la base de comparación elige el titular. Se fija antes de\n",
    "mirar el resultado.\n",
    "\n",
    "- ⚖️ Una diferencia solo significa algo junto a cuántos datos tienes. 3,2\n",
    "puntos con 3.000 filas es ruido; con 300.000 sería señal.\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 su variación normal al lado no se puede interpretar. Solo\n",
    "se puede creer."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Y si estás decidiendo si este camino es para ti, te dejo lo que hace de\n",
    "verdad una analista de datos en el día a día:\n",
    "[ser analista de datos](https://missyera.com/blog/ser-analista-de-datos/) 💛"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Qué viene ahora"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "En el capítulo 2 arreglamos las cuatro Limas y ponemos cada columna en su\n",
    "tipo, que es lo que decide qué medidas puedes usar y cuáles no tienen sentido.\n",
    "Y sí, hay medidas que se calculan sin dar error y no significan absolutamente\n",
    "nada 🙃"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Preguntas frecuentes"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "¿Para qué sirve la estadística?Para distinguir lo que pasó de verdad de lo que pasó por casualidad. Todo lo demás son herramientas para contestar eso.\n",
    "\n",
    "¿Cuál es la diferencia entre estadística descriptiva e inferencial?La descriptiva resume lo que tienes delante. La inferencial usa esa muestra para decir algo del total que no mediste, y ahí es donde aparece la incertidumbre.\n",
    "\n",
    "¿Qué es la inferencia estadística?Pasar de la muestra a la población con una medida de cuánto te puedes equivocar. Sin esa medida no es inferencia, es una suposición.\n",
    "\n",
    "¿Qué es la significancia estadística?Que la diferencia que viste es más grande de lo que el azar suele producir. No dice que sea importante para el negocio, y esas dos cosas se confunden todo el rato."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "Ese era el capítulo 1 de **Estadística desde cero**. El texto completo, con las salidas de cada bloque, está en https://missyera.com/guias/estadistica-desde-cero/es-real-o-es-ruido/\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
}
