{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Librería Numpy\n",
"\n",
"La librería numpy ofrece funciones eficientes para la manipulación y el procesamiento numérico en arrays.\n",
"\n",
"Este tipo de estructuras de almacenamiento númerico no son exactamente listas aunque puedan aparentar ese comportamiento (*duck-style*). Sus elementos son homogéneos e incluyen operaciones básicas y operaciones más complejas como álgebra lineal.\n",
"\n",
"Numpy forma parte del *core* de otras librerías como Pandas.\n",
"\n",
"\n",
"https://numpy.org/doc/stable/index.html\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": "Mediante el siguiente comando en la terminal podemos comprovar si tenemos la librería ``numpy``."
},
{
"cell_type": "code",
"metadata": {},
"source": "uv pip freeze | grep numpy",
"outputs": [],
"execution_count": null
},
{
"metadata": {},
"cell_type": "markdown",
"source": "Si no está instalada podemos hacerlo mediante el siguiente comando en la terminal."
},
{
"metadata": {},
"cell_type": "code",
"source": "uv pip install numpy",
"outputs": [],
"execution_count": null
},
{
"metadata": {},
"cell_type": "markdown",
"source": "Una vez comprobado que disponemos de la librería podemos empezar a usarla. Para usar la libreria siempre debemos importarla primero como en la siguiente celda."
},
{
"metadata": {},
"cell_type": "code",
"source": "import numpy as np",
"outputs": [],
"execution_count": null
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2025-11-03T16:05:31.693239Z",
"start_time": "2025-11-03T16:05:31.690214Z"
}
},
"cell_type": "markdown",
"source": "El resultado de la importación no tiene salida, pero ya podemos usar todas las funcionalidades de la librería."
},
{
"cell_type": "code",
"metadata": {},
"source": [
"data = np.array([1,0])\n",
"print(data[0])\n",
"print(type(data[0]))\n",
"\n",
"data = np.array([[1,0],[2,0],[3,0]])\n",
"print(data[0][:0])\n"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"print(data.shape)\n",
"print(data.size)\n",
"print(data.ndim)\n",
"print(data.dtype)"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Tipos de datos soportados:\n",
"\n",
"- int: int8, int16, int32, int64\n",
"- uint: uint8, uint16, uint32, uint64\n",
"- bool: Bool\n",
"- float: float16, float32, float64, float128\n",
"- complex: complex64, complex128, complex256 "
]
},
{
"cell_type": "code",
"metadata": {},
"source": [
"data = np.array([[1,0],[2,0]],dtype=np.int32)\n",
"data = np.array([[1,0],[2,0]],dtype=np.complex64)\n",
"data = np.array([[1,0],[2,0]],dtype=np.float16)\n",
"# Conversión\n",
"data = np.array(data,dtype=np.uint)\n",
"data = data.astype(np.bool_)\n",
"print(data)"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Generación \n",
"\n",
"No todo es cargar valores. A veces es necesario generar una muestra de puntos aleartoria, un vector neutro, o escala de valores."
]
},
{
"cell_type": "code",
"metadata": {},
"source": [
"data = np.array(range(10))\n",
"print(data)\n",
"\n",
"data = np.arange(10)\n",
"print(data)\n",
"\n",
"data = np.zeros((10,5))\n",
"# https://numpy.org/doc/stable/reference/generated/numpy.zeros.html\n",
"print(data)\n",
"\n",
"data = np.ones(10)\n",
"print(data)"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"shape = (10,80) # 10 rows x 80 cols\n",
"data = np.zeros(shape)\n",
"print(data)"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"data = np.linspace(0,1,10)\n",
"print(data)"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"data = np.logspace(0,2,10) # 10puntos entre 2**0 y 2**2\n",
"print(data)"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"data = np.identity(3)\n",
"print(data)\n",
"print(\"-\"*10)\n",
"\n",
"data = np.eye(3,k=1) # https://numpy.org/doc/stable/reference/generated/numpy.eye.html\n",
"print(data)\n",
"print(\"-\"*10)\n",
"\n",
"data = np.diag(range(1,4))\n",
"print(data)\n"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Generación o sampling aleatorio\n",
"\n",
"`Numpy` incluye un módulo específico para generación de números aleatorios: `numpy.random`. Este módulo incluye funciones para generar números aleatorios siguiendo diferentes distribuciones estadísticas, como uniforme, normal, binomial, entre otras."
]
},
{
"cell_type": "code",
"metadata": {},
"source": [
"data = np.random.rand(3,3)\n",
"print(data)\n",
"print(\"-\"*20)\n",
"\n",
"data = np.random.randint(1,10,size=(2,2))\n",
"print(data)\n",
"print(\"-\"*20)\n",
"\n",
"data = np.random.randint(1,10,20).reshape(10,2)\n",
"print(data)\n",
"print(\"-\"*20)\n",
"\n",
"data = np.array(np.random.rand(20)*10,dtype=int).reshape(10,2)\n",
"print(data)"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Actividades\n",
"\n",
"### Actividad 1\n",
"Imaginad la siguiente actividad donde tenemos que realizar la siguiente matriz:\n",
"\n",
"```\n",
"array([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],\n",
" [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],\n",
" [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],\n",
" [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],\n",
" [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],\n",
" [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],\n",
" [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],\n",
" [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],\n",
" [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],\n",
" [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]])\n",
"```\n",
"\n",
"tip: https://numpy.org/doc/stable/reference/generated/numpy.repeat.html"
]
},
{
"cell_type": "code",
"metadata": {},
"source": [
"# TODO ACTIVITY"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Actividad 2\n",
"\n",
"Generar la siguiente estructura a partir del array([1, 2, 3])\n",
"\n",
"```\n",
"array([1, 1, 1, 2, 2, 2, 3, 3, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3])\n",
"```\n",
"\n",
"tip: https://numpy.org/doc/stable/reference/generated/numpy.tile.html\n"
]
},
{
"cell_type": "code",
"metadata": {},
"source": [
"# TODO Activity"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Carga y volcado de datos\n",
"\n",
"Entrada y salida\n",
"\n",
"¿Cómo cargar datos de un fichero y cómo salvar resultados?\n",
"\n",
"Siempre hay que considerar el tipo de formato con el que se han guardado los datos. El formato influye en el rendimiento de las operaciones (R/W) y la capacidad de almacenamiento utilizada.\n",
"- CSV suele contener texto, no es eficiente, pero fácil de ingerir en otras herramientas. ¿Tiene sentido un fichero csv para matrices númericas? https://datos.gob.es/es/catalogo\n",
" \n",
"- Formatos binarios:\n",
" - npy, npz propios de numpy\n",
" - pickle - https://docs.python.org/3/library/pickle.html"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Carga de datos con Numpy\n",
"\n",
"Vamos a utilizar cualquier fichero csv (i.e. altura de gabilos) para tener en una estructura de numpy dichos valores de altura. Podeis descargar este fichero des de este [enlace](https://raw.githubusercontent.com/wisaaco/TTAD/refs/heads/main/notebooks/03_Numpy/data/GALIBOS%20TUNELES%20MADRID.csv)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": "**Recomendaciones** No pongais nombres de ficheros con espacios ni con acentos!"
},
{
"cell_type": "code",
"metadata": {},
"source": [
"# https://numpy.org/doc/stable/reference/generated/numpy.loadtxt.html\n",
"data = np.loadtxt(\"data/GALIBOS TUNELES MADRID.csv\", delimiter=\";\", usecols = 1, skiprows=1, converters={1: lambda s:float(str(s.decode()).replace(\",\",\".\"))})\n",
"print(data)\n",
"print(data.shape)"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Volviendo a trabajar con datos numéricos"
]
},
{
"cell_type": "code",
"metadata": {},
"source": [
"data = np.random.uniform(0.01,20.0,size=100000)\n",
"print(data[:5])"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"f = open(\"data/tmp.npy\",\"wb\") # Writing file, in Binary mode\n",
"np.save(f,data)\n",
"f.close()\n",
"\n",
"with open(\"data/tmp2.csv\",\"w\") as f2: # Writing but in txt\n",
" for n in data:\n",
" f2.write(str(n)+\",\")\n"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"!ls -lih data/tmp*"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"data = np.random.uniform(0.01,20.0,size=100000)\n",
"data2 = np.random.normal(0.3,10,100000)\n",
"print(data[:5])\n",
"print(data2[:5])\n",
"\n",
"f = open(\"data/tmp.npy\",\"wb\") # Writing file, in Binary mode\n",
"np.save(f,data)\n",
"np.save(f,data2)\n",
"f.close()\n",
"\n",
"print(\"saved\")\n",
"\n",
"\n",
"with open('data/tmp.npy', 'rb') as f:\n",
" a = np.load(f)\n",
" b = np.load(f)\n",
"\n",
"print(a[:5])\n",
"print(b[:5])\n"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"import pickle\n",
"\n",
"with open(\"data/tmp3.npy\",'wb') as f:\n",
" pickle.dump(a, f)\n",
" pickle.dump(b, f)\n"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"!ls -lih data/tmp*"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"f = \"data/tmp3.npy\"\n",
"ca = pickle.load(open(f,\"rb\"))\n",
"print(ca)\n",
"cb = pickle.load(open(f,\"rb\"))\n",
"print(cb)\n",
"\n",
"# Qué paso en este punto?\n",
"# ¿Cómo podriamos haber guardado ambas variables dentro del mismo fichero?"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Operaciones con series numpy\n",
"\n",
"Las operaciones básicas entre arrays de numpy son *element-wise*, es decir, se aplican elemento a elemento. Por ellos podemos hacer operaciones aritméticas básicas como suma, resta, multiplicación, división y potencias."
]
},
{
"cell_type": "code",
"metadata": {},
"source": [
"import numpy as np\n",
"a = np.array([.0,0.1])\n",
"b = np.array([1,1])\n",
"print(a+b)\n",
"print(a-b)\n",
"print(a/b)\n",
"print(a*b)\n",
"print(2**a)"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"c = np.array([1,1,1])\n",
"print(a+c) #Alerta"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"c = np.array([1,1,1,1]).reshape(2,2)\n",
"print(a*c)\n",
"print(\"-\"*10)\n",
"print(a.dot(c)) #https://numpy.org/doc/stable/reference/generated/numpy.dot.html\n"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"# Tensor dot \n",
"#https://numpy.org/doc/stable/reference/generated/numpy.tensordot.html#numpy.tensordot\n",
"a = np.arange(60.).reshape(3,4,5)\n",
"b = np.arange(24.).reshape(4,3,2)\n",
"c = np.tensordot(a,b, axes=([1,0],[0,1]))\n",
"print(c)\n",
"print(c.shape)"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"# Einseum \n",
"# https://numpy.org/doc/stable/reference/generated/numpy.einsum.html\n",
"\n",
"a = np.arange(25).reshape(5,5)\n",
"np.einsum(\"ii\",a)"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Kron product\n",
"\n",
"$$a \\otimes b$$\n",
"\n",
"> En matemáticas, se llama producto de Kronecker, denotado con ⊗, a una operación sobre dos matrices de tamaño arbitrario que da como resultado una matriz bloque. Es un caso especial del producto tensorial. El producto de Kronecker no debería confundirse con el producto de matrices habitual, que es una operación totalmente diferente. Debe su nombre al matemático alemán Leopold Kronecker.\n",
"\n",
"Definición extraida de Wikipedia ([Enlace](https://en.wikipedia.org/wiki/Kronecker_product))."
]
},
{
"cell_type": "code",
"metadata": {},
"source": [
"a = np.arange(1,5).reshape(2,2)\n",
"print(a)\n",
"b = np.array([0,5,6,7]).reshape(2,2)\n",
"print(b)\n",
"print(\"-\"*10)\n",
"k = np.kron(a,b)\n",
"print(k)\n"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Actividad\n",
"Implementa con operaciones básicas de numpy la multiplicación de Kron.
\n",
"Compara tiempos de ejecución entre tú versión y la ya implementada.\n",
"\n",
"TIP: Para comparar tiempos de ejecución mira esta [información](https://stackoverflow.com/questions/1557571/how-do-i-get-time-of-a-python-programs-execution)."
]
},
{
"cell_type": "code",
"metadata": {},
"source": [
"#TODO Activity"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Funciones sobre series\n",
"\n",
"Hay muchas funciones ya implementadas en numpy para trabajar con arrays. Vamos a ver algunas de las más comunes:\n",
"- Trigonometricas: np.cos, np.sin, np.tan\n",
"- Exponenciales y logaritmos: np.exp, np.log\n",
"- Estadísticas: `np.sum`, `np.cumsum`, `np.mean`, `np.cumprod`, `np.min`, `np.argmax`. Estas funciones también están implementadas como métodos de los arrays, `a.mean()`."
]
},
{
"cell_type": "code",
"metadata": {},
"source": [
"a = np.array(range(10))\n",
"print(np.cos(a))\n",
"print(np.exp(a))\n",
"print(np.log(a))"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"print(np.sum(a))\n",
"print(np.cumsum(a))\n",
"print(np.mean(a))\n",
"\n",
"print(\"\\n\",np.cumprod(a))\n",
"print(np.min(a))\n",
"print(np.argmax(a))\n"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"print(a.mean())\n",
"print(a.min())\n",
"print(a.argmax())"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"a = a.reshape(2,5)\n",
"print(a)\n",
"print(\"-\"*10)\n",
"print(np.sum(a,axis=1))\n",
"print(np.sum(a,axis=0))"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Actividades\n",
"\n",
"### Actividad. 1\n",
"\n",
"¿Cómo calcular la distancia euclidea entre dos vectores?\n",
"$$ d{v_1,v_2}=\\sqrt{\\sum_{k=1}^n(x_{1,k}-x_{2,k})^2} $$"
]
},
{
"cell_type": "code",
"metadata": {},
"source": [
"v1 = np.arange(1,4)\n",
"v2 = np.arange(4,7)\n",
"#TODO Activity\n",
"# Solucion == 5.196152422706632"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Actividad. 2\n",
"\n",
"¿Y calcular la distancia de Manhattan?\n",
"\n",
"$$ d{v_1,v_2}= \\sum_{k=1}^n \\mid x_{1,k} - x_{2,k} \\mid $$"
]
},
{
"cell_type": "code",
"metadata": {},
"source": [
"v1 = np.arange(1,4)\n",
"v2 = np.arange(4,7)\n",
"#TODO Activity\n",
"# Solucion == 9"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Restructurando la dimensión de una serie"
]
},
{
"cell_type": "code",
"metadata": {},
"source": [
"a = np.arange(10)\n",
"print(a.shape)\n",
"print(a.reshape(2,5))\n",
"print(a)\n"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"a = a.reshape(2,5)\n",
"print(a.T)\n",
"print(\"-\"*10)\n",
"print(np.hstack(a)) # https://numpy.org/doc/stable/reference/generated/numpy.hstack.html\n"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"b = np.arange(10,20).reshape(2,5)\n",
"print(b)\n",
"print(\"-\"*10)\n",
"print(np.hstack((a,b))) # axis-1\n",
"print(np.vstack((a,b))) # axis-0\n"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"c = np.dstack((a,b)) # axis-2 https://numpy.org/doc/stable/reference/generated/numpy.dstack.html\n",
"print(c)\n",
"print(c.shape)"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"print(a)\n",
"print(np.ravel(a)) # https://numpy.org/doc/stable/reference/generated/numpy.ravel.html\n",
"\n",
"print(np.ravel(a,order=\"F\")) # ‘F’ means to index the elements in column-major,"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"print(a)\n",
"print(np.split(a,2))\n",
"c1,c2 = np.split(a,2)\n",
"\n",
"print(\"-\"*10)\n",
"\n",
"print(c1)\n",
"print(c1.shape)\n",
"print(np.ravel(c1))\n",
"print(c2)"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"print(np.concatenate((a,b)))\n",
"print(\"-\"*10)\n",
"print(np.concatenate((a,b),axis=1))"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"# https://pillow.readthedocs.io/en/stable/"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"%pip install pillow"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"from PIL import Image\n",
"\n",
"image = Image.open('images/gatito.jpeg')\n",
"# summarize some details about the image\n",
"print(image.format)\n",
"print(image.size)\n",
"print(image.mode)\n",
"\n",
"display(image)\n"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"data = np.asarray(image)\n",
"print(len(data[0]))\n",
"print(data.size)\n",
"print(data.shape)\n",
"w,h,_ = data.shape"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"print(data[w//2,h//2])\n",
"data2 = data.copy()\n",
"data2[w//2,h//2] = np.array([255,0,0]) # a red point\n",
"\n",
"img = Image.fromarray(data2, 'RGB')\n",
"\n",
"display(img)\n"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"center_mask = w//2,h//2\n",
"rectangle_size = int(w*0.1)\n",
"mask = np.ones(rectangle_size*rectangle_size).reshape(rectangle_size,rectangle_size)\n",
"print(mask.shape)\n",
"\n",
"for x in range(w//2,w//2+rectangle_size):\n",
" for y in range(h//2,h//2+rectangle_size):\n",
" data2[x,y] = np.array([255,0,0])\n",
"\n",
"\n",
"img = Image.fromarray(data2, 'RGB')\n",
"display(img)\n",
"\n",
"# REALMENTE, el cuadrado está en el centro?\n"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Actividad\n",
"\n",
"Transforma la imagen en tonos grises. Solo con numpy!!!"
]
},
{
"cell_type": "code",
"metadata": {},
"source": [
"#WAY 1:\n",
"# \n",
"data = np.asarray(image)\n",
"data2 = data.copy()\n",
"for x in range(data2.shape[0]): #no eficiente\n",
" for y in range(data2.shape[1]):\n",
" data2[x,y] = np.repeat(data[x,y].mean(),3)\n",
"\n",
"img = Image.fromarray(data2, 'RGB')\n",
"display(img)"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Operaciones de Slicing"
]
},
{
"cell_type": "code",
"metadata": {},
"source": [
"a = np.arange(300).reshape(10,10,3)\n",
"print(a[:1])\n",
"print(\"-\"*10)\n",
"\n",
"print(a[0][0])\n",
"print(\"-\"*10)\n",
"\n",
"print(a[:,0])\n",
"print(\"-\"*10)\n",
"\n",
"print(a[:,2:4])\n",
"print(\"-\"*10)"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"a = np.arange(300).reshape(10,10,3)\n",
"print(a[:1])\n",
"print(\"-\"*10)\n",
"\n",
"print(a[:,:,0])\n",
"\n",
"print(\"-\"*10)\n",
"\n",
"r = 0.2126\n",
"print(a[:,:,0]*r)\n"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"# WAY2\n",
"# https://e2eml.school/convert_rgb_to_grayscale.html\n",
"\n",
"\n",
"# TODO\n",
"\n",
"print(data.shape)\n",
"img = Image.fromarray(np.uint8(data))\n",
"display(img)\n",
"\n"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"# Way 3\n",
"\n",
"rgbcorrection = np.array([0.2989, 0.5870, 0.1140])\n",
"\n",
"data = np.asarray(image)\n",
"print(data.shape)\n",
"data2 = np.dot(data,rgbcorrection)\n",
"\n",
"print(data2.shape)\n",
"img = Image.fromarray(np.uint8(data2))\n",
"display(img)\n",
"\n",
"\n",
"# as a plot\n",
"import matplotlib.pyplot as plt\n",
"plt.imshow(data2, cmap = plt.get_cmap(name = 'gray'))\n",
"plt.show()"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Funciones propias vectorizadas\n",
"\n",
"Las funciones vectorizadas de `NumPy` son una de las características más potentes de esta biblioteca. Permiten realizar operaciones matemáticas y lógicas sobre *arrays* completos sin necesidad de usar bucles explícitos en Python. En lugar de iterar elemento por elemento, NumPy aplica la operación de forma simultánea a todos los elementos del array, aprovechando la eficiencia de la librería.\n",
"\n",
"Esto no solo hace que el código sea más compacto y legible, sino también mucho más rápido. Por ejemplo, operaciones como la suma, multiplicación o funciones matemáticas (como `np.sin`, `np.exp` o `np.sqrt`) pueden aplicarse directamente sobre arrays enteros. En resumen, las funciones vectorizadas son clave para trabajar con grandes volúmenes de datos numéricos de forma eficiente y elegante.\n",
"\n",
"En este apartado veremos como crear nuestras propias funciones vectorizadas. Como ejemplo, vamos a definir una función que determine si una temperatura es \"caliente\" o no. Definiremos \"caliente\" como cualquier temperatura superior a 33 grados Celsius.\n",
"\n",
"Primero definimos una serie de temperaturas aleatorias para probar nuestra función usando `np.random.randint`."
]
},
{
"cell_type": "code",
"metadata": {},
"source": [
"temperatura = np.random.randint(-10,43,1000)"
],
"outputs": [],
"execution_count": null
},
{
"metadata": {},
"cell_type": "markdown",
"source": "En la *array* temperatura tenemos 1000 valores. Para saber si cada uno de esos valores es \"caliente\" o no, podemos definir una función `is_hot` que tome un valor de temperatura y devuelva `True` si es mayor a 33 grados y `False` en caso contrario."
},
{
"cell_type": "code",
"metadata": {},
"source": [
"def is_hot(grados):\n",
" if 33 < grados <= 40: # Equivalente a grados>33 and grados<=40\n",
" return True\n",
" else:\n",
" return False\n",
"\n",
"def is_hot(grados):\n",
" return 33 < grados <= 40\n",
" \n"
],
"outputs": [],
"execution_count": null
},
{
"metadata": {},
"cell_type": "markdown",
"source": "En la celda anterior podemos observar dos versiones de la misma función. Se trata de una funció normal de `python`. Si la aplicamos directamente sobre la serie `temperatura`, obtendremos un error, ya que la función no está diseñada para manejar arrays de `NumPyì directamente."
},
{
"metadata": {},
"cell_type": "code",
"source": "is_hot(temperatura)",
"outputs": [],
"execution_count": null
},
{
"metadata": {},
"cell_type": "markdown",
"source": "Para utilizar estas funciones con una *array* de `NumPy`, podemos vectorizar la función usando `np.vectorize`. Esto crea una versión vectorizada de la función que puede aplicarse a cada elemento del array de manera eficiente."
},
{
"metadata": {},
"cell_type": "code",
"source": [
"f_hot = np.vectorize(is_hot)\n",
"print(f_hot(temperatura))"
],
"outputs": [],
"execution_count": null
},
{
"metadata": {},
"cell_type": "markdown",
"source": [
"#### Alternativa con operaciones lógicas y con `map`\n",
"\n",
"Existen otras formas de aplicar condiciones lógicas sobre arrays de `NumPy`. Por ejemplo, podemos usar operaciones lógicas directamente sobre la *array* para crear una máscara booleana que indique qué elementos cumplen la condición de ser \"calientes\". Otra opción es usar la función `map` de Python para aplicar la función `is_hot` a cada elemento de la *array*.\n",
"\n",
"**Se recomienda usar las funciones vectorizadas de** `NumPy` **por su versatilidad.**"
]
},
{
"cell_type": "code",
"metadata": {},
"source": [
"# https://numpy.org/doc/stable/reference/routines.logic.html\n",
"np.logical_and(temperatura>30,temperatura<=40)"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"isHot = lambda x: (x>30 and x<=40)\n",
"index = list(map(isHot,temperatura))\n",
"temperatura[index]"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Más funciones lógicas"
]
},
{
"cell_type": "code",
"metadata": {},
"source": [
"np.random.seed(2022)\n",
"a = np.random.randint(-90,0,100)\n",
"\n",
"index = np.where(a<-80) # Alerta: Son índices\n",
"print(index)\n",
"print(a[index])"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"print(np.logical_or(a<-80,a<-90))\n"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"print(np.logical_not(np.logical_or(a<-40,a<-90)))"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Actividades\n",
"\n",
"¿Cómo podemos conseguir esta transformación?\n",
"\n",
"De\n",
"```\n",
"array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])\n",
"```\n",
"a\n",
"```\n",
"array([ 0, -1, 2, -1, 4, -1, 6, -1, 8, -1])\n",
"```"
]
},
{
"cell_type": "code",
"metadata": {},
"source": [],
"outputs": [],
"execution_count": null
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Operaciones con Grupos"
]
},
{
"cell_type": "code",
"metadata": {},
"source": [
"np.random.seed(2022)\n",
"a = np.random.randint(-30,45,100)\n",
"print(a)"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"9 in a"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"if -14 in a and not -6 in a:\n",
" print(\"Something strange\")\n",
"elif 45 in a:\n",
" print(\"No 11\")\n",
"else:\n",
" print(\"Pues está el -14 y el -6, y no el 45\")"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"#https://numpy.org/doc/stable/reference/generated/numpy.unique.html?highlight=unique#numpy.unique\n",
"\n",
"unique_a = np.unique(a) # sort but\n",
"print(unique_a)"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"unique_a, freq_a = np.unique(a,return_counts=True) \n",
"print(a)\n",
"print(len(a))\n",
"print(\"-\"*10)\n",
"print(freq_a)\n",
"print(len(freq_a))\n",
"print(\"-\"*10)\n",
"print(unique_a)\n",
"print(len(unique_a))\n",
"\n",
"# ¿Cuántos elementos repetidos hay?"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"unique_a,index_a,freq_a = np.unique(a,return_counts=True,return_index=True) \n",
"print(freq_a)\n",
"print(index_a)\n",
"print(\"-\"*10)\n",
"print(np.where(freq_a==4))\n",
"print(unique_a[17]) # se repite cuatro veces\n",
"print(unique_a[33]) # se repite cuatro veces\n",
"print(unique_a[50]) # se repite cuatro veces\n",
"\n",
"print(a[np.where(a==-7)])"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"np.sort(freq_a)"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"\n",
"print(np.array([0,4,1,2,5,7,9])[::-1])\n",
"print(np.argsort(np.array([0,4,1,2,5,7,9])))\n",
"print(np.argsort(np.array([0,4,1,2,5,7,9]))[::-1])\n",
"\n",
"print(\"-\"*10)\n",
"\n",
"index_sorted = np.argsort(freq_a)[::-1] #https://numpy.org/doc/stable/reference/generated/numpy.argsort.html\n",
"print(index_sorted)\n",
"\n"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"unique_a[index_sorted]"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Actividades\n",
"\n",
"#### Actividad 1\n",
"\n",
"- ¿Cuál es el color más frecuente en la imagen del gatito?\n",
"- Sustituye esos pixeles por un color azul: rgb=(0,0,255)"
]
},
{
"cell_type": "code",
"metadata": {},
"source": [
"from PIL import Image\n",
"\n",
"image = Image.open('images/gatito.jpeg')\n",
"#TODO\n"
],
"outputs": [],
"execution_count": null
},
{
"metadata": {},
"cell_type": "markdown",
"source": [
"### Unión y diferencia de conjuntos\n",
"\n",
"La intersección, unión y diferencia de conjuntos es una operación común en álgebra de conjuntos y análisis de datos. Numpy proporciona funciones eficientes para realizar estas operaciones en arrays:\n",
"\n",
"- `np.isin`: Comprueba si los elementos de un array están presentes en otro array.\n",
"- `np.intersect1d`: Encuentra los elementos comunes entre dos arrays.\n",
"- `np.setdiff1d`: Encuentra los elementos que están en un array pero no en otro.\n",
"- `np.union1d`: Encuentra todos los elementos únicos presentes en ambos arrays.\n",
"\n"
]
},
{
"cell_type": "code",
"metadata": {},
"source": [
"a = np.arange(10)\n",
"b = np.arange(5,15)\n",
"print(a)\n",
"print(b)\n",
"print(\"-\"*10)\n",
"print(np.isin(a,b))\n",
"print(np.intersect1d(a,b))\n",
"print(\"-\"*10)\n",
"print(np.setdiff1d(a,b))\n",
"print(np.setdiff1d(b,a))\n",
"print(\"-\"*10)\n",
"print(np.union1d(a,b))"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Actividad 2\n",
"\n",
"¿Cómo podemos conseguir encontrar valores pico, valores mayores sobre sus vecinos?\n",
"\n",
"```\n",
"array([0, 1, 2, 3, 4, 54, 6, 7, 80, 9])\n",
"array([5, 8])\n",
"```\n",
"\n",
"Un par de pistas: \n",
"- np.diff https://numpy.org/doc/stable/reference/generated/numpy.diff.html?highlight=diff#numpy.diff\n",
"- np.sign https://numpy.org/doc/stable/reference/generated/numpy.sign.html?highlight=sign#numpy.sign\n"
]
},
{
"cell_type": "code",
"metadata": {},
"source": [
"import numpy as np\n",
"\n",
"a = np.array([0, 2, 2, 3, 4, 54, 6, 7, 80, 9])\n",
"\n",
"print(np.diff(a))\n",
"print(np.sign(np.diff(a)))\n",
"print(np.diff(np.sign(np.diff(a))))\n",
"# TODO"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Actividad 3\n",
"\n",
"Existe alguna columna o fila que sólo tenga una única incógnita?\n",
"```\n",
"sudoku = np.array([[5,3,0,0,7,0,0,0,0],\n",
" [6,0,0,1,9,5,0,0,0],\n",
" [1,9,8,0,0,0,0,6,0],\n",
" [8,0,0,0,6,0,0,0,3],\n",
" [4,0,0,8,0,3,0,0,1],\n",
" [7,0,0,0,2,0,0,0,6],\n",
" [0,6,0,0,0,0,2,8,0],\n",
" [3,8,0,4,1,9,7,2,5],\n",
" [4,0,0,0,8,0,0,7,9]])\n",
"\n",
"```"
]
},
{
"metadata": {},
"cell_type": "code",
"source": [
"sudoku = np.array([[5,3,0,0,7,0,0,0,0],\n",
" [6,0,0,1,9,5,0,0,0],\n",
" [1,9,8,0,0,0,0,6,0],\n",
" [8,0,0,0,6,0,0,0,3],\n",
" [4,0,0,8,0,3,0,0,1],\n",
" [7,0,0,0,2,0,0,0,6],\n",
" [0,6,0,0,0,0,2,8,0],\n",
" [3,8,0,4,1,9,7,2,5],\n",
" [4,0,0,0,8,0,0,7,9]])\n",
"\n",
"ceros_por_fila = np.count_nonzero(sudoku == 0, axis=1)\n",
"ceros_por_col = np.count_nonzero(sudoku == 0, axis=0)\n",
"\n",
"print(ceros_por_fila, ceros_por_col)"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Funciones de estadística\n",
"\n",
"La librería `NumPy` ofrece una amplia gama de funciones estadísticas que permiten analizar y resumir datos de manera eficiente. Algunas de las funciones estadísticas más comunes en `NumPy` incluyen:\n",
"\n",
"- `np.mean()`: Calcula la media aritmética de los datos.\n",
"- `np.median()`: Encuentra la mediana de los datos.\n",
"- `np.std()`: Calcula la desviación estándar, que mide la dispersión de los datos alrededor de la media.\n",
"- `np.var()`: Calcula la varianza, que es el cuadrado de la desviación estándar.\n",
"- `np.min()` y `np.max()`: Encuentran los valores mínimo y máximo en un conjunto de datos.\n",
"- `np.percentile()`: Calcula percentiles específicos, que dividen los datos en partes iguales.\n",
"- `np.histogram()`: Crea un histograma que muestra la distribución de los datos."
]
},
{
"cell_type": "code",
"metadata": {},
"source": [
"np.random.seed(2022)\n",
"temperatures= np.random.normal(loc=17,scale=20,size=1000000)\n",
"\n",
"\n",
"# https://numpy.org/doc/stable/reference/routines.statistics.html\n",
"\n",
"print(temperatures.mean())\n"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"import matplotlib.pyplot as plot\n",
"\n",
"fig, ax = plot.subplots()\n",
"ax.plot(np.sort(temperatures))"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"np.quantile(temperatures,0.5)"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"np.percentile(a,90) #https://numpy.org/doc/stable/reference/generated/numpy.percentile.html#numpy.percentile"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"# https://numpy.org/doc/stable/reference/generated/numpy.histogram.html#numpy.histogram\n",
"hist, bin_edges = np.histogram(temperatures)\n",
"print(hist)\n",
"print(bin_edges)\n",
"\n",
"print(np.sum(hist))\n"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"import matplotlib.pyplot as plt\n",
"_ = plt.hist(temperatures, bins='auto') # arguments are passed to np.histogram\n",
"plt.title(\"Histogram with 'auto' bins\")\n",
"plt.show()"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"# https://numpy.org/doc/stable/reference/generated/numpy.linspace.html\n",
"\n",
"space = np.linspace(0,1,len(temperatures))\n",
"print(space[:10])"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"import matplotlib.pylab as plt\n",
"\n",
"temperatures_sorted = np.sort(temperatures)\n",
"fig, ax = plt.subplots()\n",
"ax.plot(temperatures_sorted,space)\n",
"#CDF?"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Gestión de alertas y errores\n",
"\n",
"En computación, una excepción es un evento que ocurre durante la ejecución de un programa que interrumpe el flujo normal de las instrucciones. Cuando se produce una excepción, el programa puede dejar de funcionar correctamente o incluso finalizar abruptamente. Las excepciones pueden ser causadas por diversos factores, como errores de programación, condiciones inesperadas en los datos de entrada, problemas de hardware, entre otros.\n",
"\n",
"Normalmente , cuando se produce una excepción, el programa genera un mensaje de error que describe la naturaleza del problema. Este mensaje puede incluir información sobre el tipo de excepción, la ubicación en el código donde ocurrió y detalles adicionales que pueden ayudar a diagnosticar y solucionar el problema."
]
},
{
"cell_type": "code",
"metadata": {},
"source": [
"a , b = 0, 3\n",
"c = b/a"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"a , b = 0, 3\n",
"try:\n",
" c = b/a\n",
"except:\n",
" print(\"error\")\n",
"finally:\n",
" print(\"Intento realizar una linea alternativa de ejecucion\")\n",
"\n",
"print(\"Esto sigue\")"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"a , b = 0, 3\n",
"try:\n",
" c = b/a\n",
"except ZeroDivisionError:\n",
" print(\"Error\")\n",
"finally:\n",
" print(\"Intento realizar una linea alternativa de ejecución\")"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"a , b = 0, 3\n",
"d={\"a\":0,\"b\":-1}\n",
"try:\n",
" print(d[\"c\"])\n",
"except ZeroDivisionError:\n",
" print(\"error\")\n",
"finally:\n",
" print(\"Intento realizar una linea alternativa de ejecucion\")"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"a , b = 0, 3\n",
"d={\"a\":0,\"b\":-1}\n",
"try:\n",
" print(d[\"c\"])\n",
"except ZeroDivisionError:\n",
" print(\"hay un cero\")\n",
"except KeyError:\n",
" print(\"Key no existente\")\n",
"finally:\n",
" print(\"Intento realizar una linea alternativa de ejecucion\")"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Docs : https://docs.python.org/3/tutorial/errors.html"
]
},
{
"cell_type": "code",
"metadata": {},
"source": [
"a , b = np.arange(10), np.arange(10,20)\n",
"\n",
"c = b/a\n",
"print(c)"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"import math\n",
"print(math.inf in c)\n",
"print(c * np.random.rand(10))"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"try:\n",
" c = b/a\n",
"except RuntimeWarning:\n",
" print(\"Capturo warning ? \") # No"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"# Puedo ignorarlos\n",
"import warnings\n",
"warnings.filterwarnings(\"ignore\")\n",
"c = b/a\n",
"print(c)"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"# Puedo gestionarlos como una excepción\n",
"np.seterr(all='raise')\n",
"c = b/a\n",
"print(c)"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"try:\n",
" c = b/a\n",
"except FloatingPointError:\n",
" print(\"Capturo warning ? \") # Yes"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Reflexiones sobre el rendimiento computacional y algorítmico\n",
"\n",
"El rendimiento de un sistema informático se puede medir mediante diversas métricas que reflejan tanto la experiencia del usuario como la eficiencia del sistema en sí.\n",
"\n",
"Principales métricas percibidas por el usuario:\n",
"- *tiempo de respuesta*, tiempo de servicio y tiempo de espera\n",
"\n",
"Principales métricas para el sistema:\n",
"- Productividad (trabajos/tiempo)\n",
"\n",
"El rendimiento está influido por:\n",
"- Hardware: tecnología, arquitectura, \n",
"- Software: sistemas operativos, lenguaje de programación, aplicaciones \n",
"- *Vuestra manera de programar!*"
]
},
{
"cell_type": "code",
"metadata": {},
"source": [
"import time\n",
"\n",
"start = time.time()\n",
"# do something\n",
"print(\"Response time: %s seconds\"%(time.time()-start))"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"import numpy as np\n",
"import time\n",
"serie = np.random.random(10000000)\n",
"\n",
"start = time.time()\n",
"b = []\n",
"for value in serie:\n",
" try:\n",
" b.append(math.sqrt(value))\n",
" except:\n",
" b.append(0)\n",
"end1 = time.time()-start\n",
"print(\"Response time: %s seconds\"%(end1))"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"start = time.time()\n",
"b = np.sqrt(serie)\n",
"end2 = time.time()-start\n",
"print(\"Response time: %s seconds\"%(end2))"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"speedup = end1/end2\n",
"print(speedup)\n",
"print(\"El programa 2 es %0.2f veces más rápido que el programa 1\"%speedup)"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Si necesitáis 1 hora de ejecución del programa 1, con el segundo solo, 3.8199 minutos.
\n",
"Si necesitáis 24 horas de ejecución del programa 1, con el segundo solo, 1.527 horas."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Atención las métricas de rendimiento suelen seguir una distribución exponencial. NO SON LINEALES!!!!"
]
},
{
"cell_type": "code",
"metadata": {},
"source": [
"times1 = []\n",
"for size in range(10,1000000,1000):\n",
" serie = np.random.random(size)\n",
" start = time.time()\n",
" b = []\n",
" for value in serie:\n",
" try:\n",
" b.append(math.sqrt(value))\n",
" except:\n",
" b.append(0)\n",
" end1 = time.time()-start\n",
" times1.append(end1)\n",
"\n",
"print(\".\")\n",
"times2 = []\n",
"for size in range(10,1000000,1000):\n",
" serie = np.random.random(size)\n",
" start = time.time()\n",
" b = np.sqrt(serie)\n",
" end2 = time.time()-start\n",
" times2.append(end2)\n"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"import matplotlib.pyplot as plt\n",
"x = list(range(len(times1)))\n",
"fig, ax = plt.subplots()\n",
"ax.plot(x, times1, label = \"programa 1\")\n",
"ax.plot(x, times2, label = \"programa 2\")\n",
"ax.legend()\n",
"plt.show()\n",
"\n",
"# No es suficientemente complejo (o sí -depende de arquitectura) para crear la curva "
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Librería Numba\n",
"\n",
"[**Numba**](https://numba.pydata.org/) es una librería de código abierto para **Python** que permite acelerar el rendimiento de código numérico mediante **compilación Just-In-Time (JIT)**. Está especialmente diseñada para trabajar con **NumPy**, aunque también puede usarse con código ``Python`` estándar que haga uso intensivo de cálculos matemáticos.\n",
"\n",
"#### ¿Qué hace Numba?\n",
"\n",
"Numba traduce funciones de Python a **código máquina optimizado**. Esto permite que las funciones numéricas se ejecuten a velocidades mucho mas altas, **sin necesidad de reescribirlas en otro lenguaje**.\n",
"\n",
"#### Instalación\n",
"\n",
"Puedes instalar Numba fácilmente con `pip` o `conda`:\n",
"\n",
"```\n",
"uv pip install numba\n",
"```\n"
]
},
{
"cell_type": "code",
"metadata": {},
"source": [
"import multiprocessing\n",
"\n",
"multiprocessing.cpu_count()"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"from numba import njit\n",
"import random\n",
"\n",
"\n",
"def monte_carlo_pi_sinParalelizar(nsamples):\n",
" acc = 0\n",
" for i in range(nsamples):\n",
" x = random.random()\n",
" y = random.random()\n",
" if (x ** 2 + y ** 2) < 1.0:\n",
" acc += 1\n",
" return 4.0 * acc / nsamples\n",
"\n",
"@njit\n",
"def monte_carlo_pi(nsamples):\n",
" acc = 0\n",
" for i in range(nsamples):\n",
" x = random.random()\n",
" y = random.random()\n",
" if (x ** 2 + y ** 2) < 1.0:\n",
" acc += 1\n",
" return 4.0 * acc / nsamples"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"%timeit monte_carlo_pi_sinParalelizar(100)"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"metadata": {},
"source": [
"%timeit monte_carlo_pi(100)"
],
"outputs": [],
"execution_count": null
}
],
"metadata": {
"kernelspec": {
"display_name": "my3110",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.0rc2"
},
"orig_nbformat": 4
},
"nbformat": 4,
"nbformat_minor": 2
}