{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Un vector no es una flecha, es una fila de tu tabla\n",
    "\n",
    "Qué es un vector de verdad en machine learning, por qué el dibujo de la flecha te va a estorbar, y la diferencia entre fila y columna.\n",
    "\n",
    "Cuaderno de soluciones del capítulo 2 de **Matemática para machine learning**, 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/matematica-para-machine-learning/que-es-un-vector/\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": [
    "## Antes de empezar"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import urllib.request\n",
    "\n",
    "# Este capitulo abre el archivo por su nombre, sin URL, que es lo que se hace\n",
    "# cuando lo tienes al lado. Aqui se baja primero para que exista.\n",
    "for nombre in ['ventas-miss-yera.csv']:\n",
    "    urllib.request.urlretrieve(f\"https://missyera.com/static/datasets/{nombre}\", nombre)\n",
    "    print(nombre, \"lista\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Te tengo que quitar un dibujo de la cabeza 🌸"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Si en el colegio te enseñaron vectores, casi seguro te los enseñaron como\n",
    "una flecha. Una flecha con su origen, su dirección y su largo.\n",
    "\n",
    "Ese dibujo no está mal, pero te va a estorbar. Porque en machine learning\n",
    "un vector típico tiene cincuenta componentes, y una flecha en cincuenta\n",
    "dimensiones no se puede dibujar ni imaginar.\n",
    "\n",
    "Así que lo cambiamos por otro que sí escala: **un vector es una fila\n",
    "de tu tabla** 🐣"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Volvemos a abrir el archivo"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Cada capítulo arranca de cero, así que estas líneas se repiten. Son las\n",
    "mismas del capítulo 1 y las vas a ver en todos."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "\n",
    "df = pd.read_csv('ventas-miss-yera.csv')\n",
    "for c in ('unidades', 'monto', 'satisfaccion'):\n",
    "    df[c] = pd.to_numeric(df[c], errors='coerce')\n",
    "X = df[['unidades', 'monto', 'satisfaccion']].dropna().to_numpy()\n",
    "print('X.shape:', X.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Saca una fila y míralo"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "v = X[0]\n",
    "print('v       :', np.round(v, 2))\n",
    "print('v.shape :', v.shape, '| ndim:', v.ndim)\n",
    "print('len(v)  :', len(v))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Eso es un vector. Tres números en un orden que significa algo: primero las\n",
    "unidades, después el monto, después la satisfacción.\n",
    "\n",
    "Fíjate en `ndim: 1`. Una **dimensión**. La matriz\n",
    "del capítulo anterior tenía dos. Y la forma sale `(3,)`, con esa\n",
    "coma sola al final, que es la manera que tiene NumPy de decirte \"esto no es una\n",
    "tabla de 3 por algo, es una lista de 3\"."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## El orden es el vector"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Esto es lo que separa un vector de un montón de números sueltos.\n",
    "\n",
    "Si te doy `[10, 480.37, 4]` sabes que fueron 10 unidades por\n",
    "480.37 soles con satisfacción 4. Si te doy `[4, 10, 480.37]` son los\n",
    "mismos tres números y ya no significan nada, porque la posición es la que dice\n",
    "qué es cada uno."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "𝐯∈ℝd\n",
    "\n",
    "v es una lista de d números reales, y esa negrita es lo único que la distingue de un número suelto"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "La **d** es cuántas componentes tiene. Y la negrita de la\n",
    "**v** no es decorativa: en los papers es lo único que distingue un\n",
    "vector de un número suelto. Cuando veas una letra en negrita, es una lista."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "𝐯=(v1,v2,…,vd)\n",
    "\n",
    "un vector se escribe como sus componentes, una por cada cosa que mediste"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "| Símbolo | Qué es |\n",
    "|---|---|\n",
    "| **v** | el vector entero |\n",
    "| **v1** | su primera componente, en nuestro caso las unidades |\n",
    "| **d** | cuántas componentes tiene |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Y ojo con algo que confunde a todo el mundo: en matemática las componentes\n",
    "se numeran desde 1, y en Python desde 0. Así que la v1\n",
    "del paper es `v[0]` en tu código. No hay forma de que eso deje de\n",
    "molestar, solo se acostumbra uno 🙂"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Una columna también es un vector"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "montos = X[:, 1]\n",
    "print('montos.shape :', montos.shape)\n",
    "print('primeros 3   :', np.round(montos[:3], 2))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "2.238 componentes. También es un vector, y también tiene un orden que\n",
    "significa algo: cada posición es una venta distinta.\n",
    "\n",
    "Y aquí está la idea que quiero que te lleves de este capítulo: la\n",
    "**misma tabla** te da dos familias de vectores según cómo la\n",
    "cortes. Por filas te da un vector por venta. Por columnas te da un vector por\n",
    "característica.\n",
    "\n",
    "Las dos se usan, y para cosas distintas. Cuando en machine learning se dice\n",
    "\"cada ejemplo es un punto en el espacio\", se está hablando de los de fila.\n",
    "Cuando se dice \"esta columna correlaciona con aquella\", de los de columna."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Fila o columna, que sí importa"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "En matemática un vector suele escribirse como columna, y eso a veces hay que\n",
    "decírselo a NumPy:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fila = v.reshape(1, -1)\n",
    "col  = v.reshape(-1, 1)\n",
    "print('fila.shape', fila.shape, ' col.shape', col.shape)\n",
    "print(np.round(col, 2))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Los tres son el mismo vector con los mismos tres números. Lo que cambia es\n",
    "la forma: `(3,)`, `(1, 3)` y `(3, 1)`.\n",
    "\n",
    "El `-1` del `reshape` quiere decir \"calcula tú cuánto\n",
    "va aquí\". Es cómodo y es peligroso: si te equivocas de eje, NumPy no protesta,\n",
    "te devuelve algo con la forma que pediste y el error aparece tres funciones más\n",
    "allá.\n",
    "\n",
    "Cuándo importa: cuando multipliques. Ahí `(1, 3)` y\n",
    "`(3, 1)` dan resultados completamente distintos, y eso es el capítulo\n",
    "del producto punto."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Lo que te llevas"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- Un vector es una lista ordenada de números. Olvídate de la flecha.\n",
    "\n",
    "- La **posición** es la que dice qué es cada número.\n",
    "\n",
    "- Forma `(3,)` con coma suelta quiere decir una dimensión.\n",
    "\n",
    "- Las filas y las columnas de tu tabla son las dos vectores, y se usan para\n",
    "cosas distintas.\n",
    "\n",
    "- Los papers numeran desde 1 y Python desde 0. Es así y ya."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Comprueba que se entendió"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Comprueba que lo tienes\n",
    "\n",
    "Sacas v = X[0] y te sale forma (3,). Después haces v.reshape(-1, 1). ¿Qué cambió?\n",
    "\n",
    "a) Solo la forma: los mismos tres números organizados como columna\n",
    "\n",
    "b) Los números, que ahora están al revés\n",
    "\n",
    "c) Nada, porque (3,) y (3, 1) son lo mismo\n",
    "\n",
    "d) Ahora hay tres vectores de un número cada uno\n",
    "\n",
    "---\n",
    "\n",
    "**La correcta es la a.**\n",
    "\n",
    "*b)* Eso sería v[::-1]. El reshape no toca el orden, solo reorganiza.\n",
    "\n",
    "*c)* Se parecen y no lo son: una tiene una dimensión y la otra dos. Cuando multipliques te va a dar resultados distintos.\n",
    "\n",
    "*d)* Sigue siendo un solo objeto. Lo que tiene es tres filas de una columna.\n",
    "\n",
    "Los números nunca cambian con reshape. Lo que cambia es la forma, y la forma es la que decide qué pasa cuando multipliques 🌸"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Ejercicios"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1. Fila contra columna\n",
    "\n",
    "Comprueba que las tres formas llevan los mismos números."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(np.array_equal(v, v.reshape(1, -1).ravel()))\n",
    "print(np.array_equal(v, v.reshape(-1, 1).ravel()))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "True\n",
    "True\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`ravel` los aplasta de vuelta a una dimensión. Los números nunca\n",
    "cambiaron: lo único que cambió fue cómo NumPy los tiene organizados."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. El vector de una columna concreta\n",
    "\n",
    "Saca las satisfacciones y mira cuántas hay de cada nota."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sat = X[:, 2]\n",
    "valores, cuantos = np.unique(sat, return_counts=True)\n",
    "for v_, c_ in zip(valores, cuantos):\n",
    "    print(int(v_), '->', c_)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "1 -> 454\n",
    "2 -> 426\n",
    "3 -> 447\n",
    "4 -> 449\n",
    "5 -> 462\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ese vector de 2.238 componentes resumido en cinco números. Y fíjate en lo\n",
    "plano que sale: las cinco notas aparecen casi la misma cantidad de veces. Eso\n",
    "no es lo que uno esperaría de clientes reales, y es una pista de que este\n",
    "archivo está generado. Un vector resumido así te dice en cinco números si tus\n",
    "datos tienen forma o no la tienen."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3. El orden importa, demuéstralo\n",
    "\n",
    "Desordena las componentes y mira si sigue significando lo\n",
    "mismo."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print('original :', np.round(v, 2))\n",
    "print('al reves :', np.round(v[::-1], 2))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "original : [ 10.   480.37   4.  ]\n",
    "al reves : [  4.   480.37  10.  ]\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Los mismos tres números. Pero el segundo dice 4 unidades y satisfacción 10,\n",
    "que ni siquiera existe porque la escala llega a 5. Un vector desordenado no es\n",
    "un vector distinto: es basura."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Preguntas frecuentes"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "¿Qué es un vector?Una lista ordenada de números. En machine learning, una fila de tu tabla es un vector: un cliente son sus cinco números puestos en fila y en el mismo orden siempre.\n",
    "\n",
    "¿Qué son las componentes de un vector?Cada uno de los números de la lista. Si el vector es un cliente, sus componentes son unidades, monto, descuento y lo que hayas medido.\n",
    "\n",
    "¿Qué tipos de vectores hay?En el álgebra que hace falta acá, la distinción que importa es fila o columna, y es de forma y no de fondo. NumPy te lo va a recordar el día que dos formas no encajen.\n",
    "\n",
    "¿Cómo se suman dos vectores?Componente a componente: el primero con el primero, el segundo con el segundo. Solo se pueden sumar si tienen el mismo largo."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "Ese era el capítulo 2 de **Matemática para machine learning**. El texto completo, con las salidas de cada bloque, está en https://missyera.com/guias/matematica-para-machine-learning/que-es-un-vector/\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
}
