{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Qué puedes calcular con cada columna\n",
    "\n",
    "Nominal, ordinal, discreta y continua. Y las cuentas que salen sin dar error y no significan nada.\n",
    "\n",
    "Cuaderno de práctica del capítulo 2 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/tipos-de-variable/\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: \"Y2xpZW50ZXMgZGlzdGludG9zOiA2MTcKdmVudGFzIHBvciBjbGllbnRlOiA0Ljg2CmNvdW50ICAgIDYxNy4wMAptZWFuICAgICAgIDQuODYKc3RkICAgICAgICAyLjE5Cm1pbiAgICAgICAgMS4wMAoyNSUgICAgICAgIDMuMDAKNTAlICAgICAgICA1LjAwCjc1JSAgICAgICAgNi4wMAptYXggICAgICAgMTQuMDAKTmFtZTogY291bnQsIGR0eXBlOiBmbG9hdDY0\",\n",
    "    2: \"aWRfdmVudGEgICAgICAgICAgICAgICAgICAzMDAwIGRpc3RpbnRvcwp1bmlkYWRlcyAgICAgICAgICAgICAgICAgICAgMzAgZGlzdGludG9zCm1vbnRvICAgICAgICAgICAgICAgICAgICAgMjk2NCBkaXN0aW50b3MKZGVzY3VlbnRvICAgICAgICAgICAgICAgICAgMjUxIGRpc3RpbnRvcwpzYXRpc2ZhY2Npb24gICAgICAgICAgICAgICAgIDUgZGlzdGludG9zICA8LS0gY2F0ZWdvcmljYSBkaXNmcmF6YWRhCmNvbXBybyAgICAgICAgICAgICAgICAgICAgICAgMiBkaXN0aW50b3MgIDwtLSBjYXRlZ29yaWNhIGRpc2ZyYXphZGEKbW9udG9fZmluYWxfZmFjdHVyYWRvICAgICAxNzIzIGRpc3RpbnRvcw==\",\n",
    "    3: \"ZmlsYXMgdG90YWxlczogICAgICAgMzAwMApkZXNjdWVudG9zIGNvbiBkYXRvOiAyNDA1Cm1lZGlhIGlnbm9yYW5kbyBodWVjb3M6IDAuMTI1MgptZWRpYSBjb24gaHVlY29zID0gMDogICAwLjEwMDQ=\",\n",
    "    4: \"Y291bnQgICAgMjQ1Ni4wMAptZWFuICAgICAgIDcyLjgyCnN0ZCAgICAgICAxOTAuMzMKbWluICAgICAgLTM4NS4wMAoyNSUgICAgICAgLTY1LjAwCjUwJSAgICAgICAgNjkuMDAKNzUlICAgICAgIDIxMy4yNQptYXggICAgICAgNTIyLjAwCmR0eXBlOiBmbG9hdDY0Cm5lZ2F0aXZvczogOTA0\",\n",
    "    5: \"ICAgICAgICAgICAgICBtZWFuICBtZWRpYW4gIGNvdW50CnNlZ21lbnRvCkJvZGVnYSAgICAgIDIuOTYwMyAgICAgMy4wICAgIDY1NQpIb3JlY2EgICAgICAzLjAzMzIgICAgIDMuMCAgICA2OTIKTWF5b3Jpc3RhICAgMi45OTI3ICAgICAzLjAgICAgNjg0Ck1pbmltYXJrZXQgIDMuMDQ3NCAgICAgMy4wICAgIDczOA==\",\n",
    "    6: \"bWVkaWEgc29icmUgbGFzIDMwMDAgZmlsYXM6ICAgICAgNDgxLjI2Cm1lZGlhIHNvbG8gc29icmUgbG9zIHF1ZSBjb21wcmFyb246IDgzMy4xMApjdWFudG9zIGNlcm9zOiAxMjY3\",\n",
    "    7: \"KDMwMDAsIDE0KQo2IGNpdWRhZGVzIHwgZmxvYXQ2NCB8IGZlY2hhczogZGF0ZXRpbWU2NFt1c10=\",\n",
    "    8: \"aWRfdmVudGEgICAgICAgICAgICAgICBpbnQ2NCAgICAgICAgICAgICAzMDAwIGRpc3RpbnRvcwpmZWNoYSAgICAgICAgICAgICAgICAgIGRhdGV0aW1lNjRbdXNdICAgICA1MzcgZGlzdGludG9zCmNsaWVudGVfaWQgICAgICAgICAgICAgc3RyICAgICAgICAgICAgICAgIDYxNyBkaXN0aW50b3MKY2l1ZGFkICAgICAgICAgICAgICAgICBzdHIgICAgICAgICAgICAgICAgICA2IGRpc3RpbnRvcwpzZWdtZW50byAgICAgICAgICAgICAgIHN0ciAgICAgICAgICAgICAgICAgIDQgZGlzdGludG9zCmNhbmFsICAgICAgICAgICAgICAgICAgc3RyICAgICAgICAgICAgICAgICAgNCBkaXN0aW50b3MKY2F0ZWdvcmlhICAgICAgICAgICAgICBzdHIgICAgICAgICAgICAgICAgICA1IGRpc3RpbnRvcwp1bmlkYWRlcyAgICAgICAgICAgICAgIGludDY0ICAgICAgICAgICAgICAgMzAgZGlzdGludG9zCm1vbnRvICAgICAgICAgICAgICAgICAgZmxvYXQ2NCAgICAgICAgICAgMjk2NCBkaXN0aW50b3MKZGVzY3VlbnRvICAgICAgICAgICAgICBmbG9hdDY0ICAgICAgICAgICAgMjUxIGRpc3RpbnRvcwpmZWNoYV91bHRpbWFfY29tcHJhICAgIGRhdGV0aW1lNjRbdXNdICAgICAzOTkgZGlzdGludG9zCnNhdGlzZmFjY2lvbiAgICAgICAgICAgZmxvYXQ2NCAgICAgICAgICAgICAgNSBkaXN0aW50b3MKY29tcHJvICAgICAgICAgICAgICAgICBpbnQ2NCAgICAgICAgICAgICAgICAyIGRpc3RpbnRvcwptb250b19maW5hbF9mYWN0dXJhZG8gIGZsb2F0NjQgICAgICAgICAgIDE3MjMgZGlzdGludG9z\",\n",
    "    9: \"c2VnbWVudG9fb3JkZW4KQm9kZWdhICAgICAgICAgMTgzLjI2Ck1pbmltYXJrZXQgICAgIDQxMy43NApIb3JlY2EgICAgICAgICA3NDMuMDAKTWF5b3Jpc3RhICAgICAxODY5LjI2CgphaG9yYSBzaSBzZSBwdWVkZSBwcmVndW50YXIgcG9yIGVsIG9yZGVuOgoxNDkyIHBlZGlkb3Mgc29uIGRlIEhvcmVjYSBvIE1heW9yaXN0YQ==\",\n",
    "}, lenguaje=\"python\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "En el capítulo 1 vimos que las ventas se mueven 14,41% al mes, y que había\n",
    "nueve ciudades donde tenía que haber seis 🙃\n",
    "\n",
    "Este capítulo arregla eso y contesta una pregunta que parece de manual y es\n",
    "de las más prácticas del libro: **¿qué puedo calcular con cada\n",
    "columna?**\n",
    "\n",
    "Porque tu computadora no lo sabe. Le pides la media de lo que sea y te la\n",
    "da. El problema es que la mitad de esas medias no significan nada, y no hay\n",
    "ningún mensaje de error que te avise 😶\n",
    "\n",
    "Y dime si te suena: **¿alguna vez reportaste un promedio sin preguntarte si tenía sentido promediarlo?** Todas lo hicimos. Este capítulo va de que no vuelva a pasar 😶"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Primero la limpieza, que si no todo lo demás miente"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Tres cosas por orden.\n",
    "\n",
    "**Uno: las filas repetidas.** Se van primero, porque una fila\n",
    "duplicada cuenta dos veces en todas las medidas que vengan después."
   ]
  },
  {
   "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('filas:', len(v), '| duplicadas enteras:', v.duplicated().sum())\n",
    "\n",
    "v = v.drop_duplicates()\n",
    "print('quedan:', len(v))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "37 filas idénticas. No es que se parezcan: son la misma venta escrita dos\n",
    "veces, con el mismo identificador y todo.\n",
    "\n",
    "**Dos: las cuatro Limas.**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(v['ciudad'].value_counts())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ahí está la trampa entera: `lima`, `Líma`,\n",
    "`Lima` y `LIMA`. Para ti son la misma ciudad. Para pandas\n",
    "son cuatro textos distintos, y ninguno se parece más al otro que a\n",
    "`Piura`.\n",
    "\n",
    "Se arregla en una línea encadenada:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "v['ciudad'] = (v['ciudad'].str.strip().str.lower()\n",
    "               .str.normalize('NFKD')\n",
    "               .str.encode('ascii', 'ignore').str.decode('utf-8'))\n",
    "\n",
    "print(v['ciudad'].value_counts())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Seis ciudades 🎉 Y Lima pasa de aparentar 123 ventas a tener 471, que la\n",
    "pone empatada con Trujillo.\n",
    "\n",
    "Lo que hace cada trozo, por si te lo preguntas: `strip` quita\n",
    "espacios de los bordes, `lower` pasa todo a minúscula, y ese\n",
    "`normalize('NFKD')` con el `encode/decode` es el truco que\n",
    "convierte `í` en `i`. Descompone la letra acentuada en\n",
    "letra más tilde y luego tira lo que no sea ASCII.\n",
    "\n",
    "**Tres: los números que llegaron como texto.**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(v.dtypes.head(9))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`monto` es `str`, o sea texto. Y ya sabemos por qué:\n",
    "trae comas decimales al estilo peruano, y pandas ante la duda no toca nada."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "v['monto'] = pd.to_numeric(v['monto'].str.replace(',', '.'))\n",
    "print(v['monto'].dtype, '| media: %.2f' % v['monto'].mean())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Los cuatro tipos, con lo que puedes hacer con cada uno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ahora la parte que te va a servir para el resto del libro. Cada columna es\n",
    "de uno de estos cuatro tipos 👇"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "| Tipo | Qué es | En este archivo | Qué puedes calcular |\n",
    "|---|---|---|---|\n",
    "| **Nominal** | Categorías sin orden | ciudad, segmento, canal, categoria | Frecuencias y moda. Nada más. |\n",
    "| **Ordinal** | Categorías con orden, pero sin distancia fija | satisfaccion (1 a 5) | Mediana, percentiles, moda |\n",
    "| **Discreta** | Números que se cuentan, sin partes | unidades | Todo, y la media puede salir con decimales |\n",
    "| **Continua** | Cualquier valor dentro de un rango | monto, descuento | Todo: media, desviación, correlación |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "La frontera que más se discute es la de ordinal. Satisfacción va de 1 a 5 y\n",
    "tiene orden clarísimo: 5 es mejor que 4. Pero **la distancia no es\n",
    "fija**. Pasar de 1 a 2 no es lo mismo, para el cliente, que pasar de 4 a\n",
    "5. Y como no lo es, sumar y dividir es discutible.\n",
    "\n",
    "Yo la uso así, y te lo digo como criterio práctico y no como ley: la mediana\n",
    "de satisfacción es la medida honesta; la media se puede reportar al lado, pero\n",
    "no se pelea por dos décimas 🤷"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Ahora el error de verdad"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Pídele a pandas la media de una columna de texto:"
   ]
  },
  {
   "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['ciudad'].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": [
    "Perfecto, ¿no? Te para en seco. Ese error es tu amigo.\n",
    "\n",
    "El problema es el caso de al lado, que es el mismo disparate y **no\n",
    "para nada**:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(v[['id_venta', 'unidades', 'monto', 'satisfaccion', 'compro']]\n",
    "      .describe().round(2))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Mira la primera columna. **La media de `id_venta` es\n",
    "11499.50.**\n",
    "\n",
    "Eso es el número de factura promedio. No existe. No significa nada. No se\n",
    "puede hacer nada con él. Y ahí está, con dos decimales, tan formal como los\n",
    "demás 😅\n",
    "\n",
    "`id_venta` es un identificador: son números por comodidad, pero\n",
    "funcionan como nombres. Es tan nominal como `ciudad`. La diferencia\n",
    "es que ciudad se escribe con letras y por eso pandas te frena, y este se escribe\n",
    "con dígitos y por eso pandas calcula.\n",
    "\n",
    "**La lección: que una cuenta salga no quiere decir que signifique\n",
    "algo.** El único que sabe qué es cada columna eres tú.\n",
    "\n",
    "De paso, en esa misma tabla hay dos cosas más que vale la pena que veas:\n",
    "\n",
    "- 💸 El mínimo de `monto` es **-2497.72**. Hay ventas\n",
    "negativas. Las miramos en el capítulo 6.\n",
    "\n",
    "- 🕳️ El `count` de `satisfaccion` es **2769**\n",
    "y no 3000. Faltan 231 valores, y la media se calculó ignorándolos sin decir ni\n",
    "pío."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Cómo se detecta el tipo cuando no conoces los datos"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Truco de campo, y de los que más uso: cuenta cuántos valores distintos tiene\n",
    "cada columna 🔎"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(v.nunique().sort_values())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Léelo de arriba abajo y el archivo se te ordena solo:\n",
    "\n",
    "- 🔢 Lo de arriba, con 2 a 6 valores distintos, es categórico. Da igual que\n",
    "`compro` y `satisfaccion` estén escritos con números.\n",
    "\n",
    "- 📈 Lo de abajo, con cientos o miles de valores distintos, es continuo o\n",
    "identificador.\n",
    "\n",
    "- 🚩 Y hay una bandera roja evidente: `id_venta` tiene 3000\n",
    "valores distintos en 3000 filas. Una columna con tantos valores distintos como\n",
    "filas es un identificador, siempre."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Una media que sí significa algo, y mucho"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Para que no te quedes con que las medias de columnas 0/1 son sospechosas,\n",
    "mira este caso, que es justo al revés:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print('media de compro:  %.4f' % v['compro'].mean())\n",
    "print('cuantos compraron: %d de %d' % (v['compro'].sum(), len(v)))\n",
    "print('proporcion:       %.4f' % (v['compro'].sum() / len(v)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "La media de una columna que solo tiene ceros y unos **es la\n",
    "proporción**. Exactamente el mismo número.\n",
    "\n",
    "Y eso es utilísimo: cada vez que quieras un porcentaje de \"cuántos\n",
    "cumplen X\", conviertes a 0/1 y pides la media. Lo vamos a usar en todo el libro,\n",
    "y en el capítulo 13 esa proporción es la que se compara entre grupos.\n",
    "\n",
    "O sea que `compro` es nominal, su media técnicamente no debería\n",
    "significar nada, y significa muchísimo. La regla no es mecánica: es que\n",
    "**tienes que saber qué representa el número** 🧠"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Y dos más, que son este capítulo en estado puro"
   ]
  },
  {
   "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['ciudad'].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": [
    "Ahí está el capítulo entero en un mensaje: **a una nominal no se le calcula la media**. No es que quede feo, es que la operación no existe. Y fíjate que pandas te lo dice mirando el tipo, no el significado: lo que le molesta es que sea texto."
   ]
  },
  {
   "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['satisfaccion'].astype(int)\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",
    "IntCastingNaNError: Cannot convert non-finite values (NA or inf) to integer.Replace or remove non-finite values or cast to an integer typethat supports these values (e.g. 'Int64')\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "La satisfacción va de 1 a 5 y parece entera, pero le faltan valores. Y un entero no puede estar vacío: no existe el \"número entero ausente\". Por eso pandas la guarda como decimal en cuanto hay un solo hueco, y por eso pasarla a entero te obliga primero a decidir qué haces con los que faltan 🕳️"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Practica 💪"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1. ¿Cuántos clientes hay de verdad?\n",
    "\n",
    "El archivo tiene 3.000 ventas. ¿De cuántos clientes\n",
    "distintos? ¿Y cuántas ventas hace un cliente típico?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 1\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. Caza las categóricas disfrazadas de números\n",
    "\n",
    "Escribe algo que recorra las columnas numéricas y te avise\n",
    "de cuáles son sospechosas de ser categorías."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 2\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3. La media que ignora los huecos\n",
    "\n",
    "La columna `descuento` tiene vacíos. Calcula su\n",
    "media, y luego calcúlala tratando los vacíos como cero. ¿Cuál está bien?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 3\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4. Fabrica una variable continua: la recencia\n",
    "\n",
    "Con `fecha` y `fecha_ultima_compra`,\n",
    "calcula cuántos días hacía que ese cliente no compraba. Mira bien el resultado\n",
    "antes de darlo por bueno."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 4\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 5. Ordinal: ¿media o mediana?\n",
    "\n",
    "Compara la satisfacción entre segmentos con las dos\n",
    "medidas. ¿Cuál cuenta mejor lo que pasa?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 5\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 6. La columna que solo existe si la venta se cerró\n",
    "\n",
    "Saca la media de `monto_final_facturado` sobre\n",
    "todas las filas y luego solo sobre las que compraron. Explica la diferencia."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 6\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 7. La limpieza completa, en una función\n",
    "\n",
    "Junta todo lo del capítulo en algo que puedas pegar al\n",
    "inicio de cualquier cuaderno."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 7\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 8. La ficha de tipos de toda la tabla\n",
    "\n",
    "Saca de un tirón el tipo que pandas le puso a cada columna y cuántos valores distintos tiene."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 8\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 9. Convertir una ordinal en ordinal de verdad\n",
    "\n",
    "Dile a pandas que el segmento tiene orden, y comprueba que después se puede comparar."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 9\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## La satisfacción media que no describe a nadie"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Y ahora el número más publicado y menos defendible que existe en las empresas. Está en la mitad de los reportes que he visto 😳"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### La trampa\n",
    "\n",
    "Reportas la satisfacción media del mes. Sale 3,01 sobre 5, o sea justo en el medio, así que escribes que los clientes están neutrales.\n",
    "\n",
    "```\n",
    "print(round(v['satisfaccion'].mean(), 2))\n",
    "# 3.01\n",
    "\n",
    "print(v['satisfaccion'].value_counts().sort_index())\n",
    "# 1.0    560\n",
    "# 2.0    537\n",
    "# 3.0    551\n",
    "# 4.0    558\n",
    "# 5.0    563\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",
    "describe() te devuelve que la media de id_venta es 11499,50. ¿Qué haces?\n",
    "\n",
    "a) Nada, es un identificador y esa media no significa nada\n",
    "\n",
    "b) La reporto como el número de factura promedio\n",
    "\n",
    "c) Reviso si hay un error en los datos\n",
    "\n",
    "d) La uso para detectar facturas fuera de rango"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Lo que te llevas"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 🧹 Duplicados primero, textos normalizados después, tipos al final. En ese\n",
    "orden, porque cada paso ensucia al siguiente si se hace al revés.\n",
    "\n",
    "- 🏙️ Cuatro formas de escribir Lima son cuatro ciudades para el software.\n",
    "strip, lower y normalize lo arreglan en una línea.\n",
    "\n",
    "- 📊 Nominal solo admite frecuencias y moda; ordinal, mediana; discreta y\n",
    "continua, todo.\n",
    "\n",
    "- 🤖 El software no conoce esa diferencia. `describe()` te dará la\n",
    "media de un número de factura y se quedará tan tranquilo.\n",
    "\n",
    "- 🔎 `nunique()` es el mejor detector de tipos que hay. Pocos\n",
    "valores distintos, categoría; tantos valores como filas, identificador.\n",
    "\n",
    "- 0️⃣ La media de una columna de ceros y unos es la proporción, y esa sí\n",
    "significa muchísimo.\n",
    "\n",
    "- 🕳️ `mean()` ignora los nulos sin avisar. Aquí eran 595 celdas y\n",
    "movían el descuento medio dos puntos y medio.\n",
    "\n",
    "Y si de todo el capítulo te llevas una sola frase, que sea esta:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Tu computadora calcula la media de lo que sea. Decidir si eso significa\n",
    "algo es tuyo."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Qué viene ahora"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "En el capítulo 3 nos metemos con la medida más usada y peor usada del mundo:\n",
    "la media. Con un caso donde la media dice 803 soles, la mediana dice 533 y la\n",
    "diferencia entre las dos es una decisión de negocio 💰"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "Ese era el capítulo 2 de **Estadística desde cero**. El texto completo, con las salidas de cada bloque, está en https://missyera.com/guias/estadistica-desde-cero/tipos-de-variable/\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
}
