{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 8. Numpy\n", "---------------------\n", "\n", "Numpy es la biblioteca central para la computación científica en Python. Proporciona un objeto de matriz multidimensional de alto rendimiento y herramientas para trabajar con estas matrices. \n", "Además de sus usos científicos obvios, NumPy también puede ser utilizado como un eficiente contenedor multidimensional de datos genéricos. Se pueden definir tipos de datos arbitrarios. Esto permite a NumPy integrarse de forma transparente y rápida con una amplia variedad de bases de datos.\n", "\n", "## Arrays\n", "\n", "Una matriz numpy es una cuadrícula de valores, __todos del mismo tipo__, y es indexada por una tupla de enteros no negativos. El número de dimensiones es el rango de la matriz; La forma de una matriz es una tupla de enteros que da el tamaño de la matriz a lo largo de cada dimensión.\n", "\n", "Podemos inicializar matrices numpy de listas anidadas de Python y acceder a elementos usando corchetes:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n" ] } ], "source": [ "import numpy as np # importamos numpy como np*\n", "\n", "a = np.array([23, 12, 94]) # Crea un array de rango 1\n", "print(type(a)) " ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(3,)\n" ] } ], "source": [ "print(a.shape) # Imprime la forma del array" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "23 12 94\n", "[ 2 12 94]\n" ] } ], "source": [ "print(a[0], a[1], a[2]) # Los indices son iguales de las listas\n", "a[0] = 2 # Podemos modificar los elementos de un array (son mutables)\n", "print(a) " ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[10 12 13]\n", " [24 25 26]]\n" ] } ], "source": [ "b = np.array([[10,12,13],[24,25,26]]) # Crea un array de rango 2\n", "print(b)" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(2, 3)\n" ] } ], "source": [ "print(b.shape)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "10 12 24\n" ] } ], "source": [ "print(b[0, 0], b[0, 1], b[1, 0]) " ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[1 2 3]\n", " [4 5 6]\n", " [7 8 9]]\n" ] } ], "source": [ "# Una mejor manera de definir un array seria asi:\n", "M = np.array([\n", " [1, 2, 3],\n", " [4, 5, 6],\n", " [7, 8, 9]\n", " ]) \n", "\n", "print(M)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Numpy también viene con numerosas funciones para crear arrays:" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ 0. 0. 0.]\n", " [ 0. 0. 0.]\n", " [ 0. 0. 0.]]\n" ] } ], "source": [ "a = np.zeros((3,3)) # Crea una matriz de ceros\n", "print(a)" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ 1. 1. 1.]\n", " [ 1. 1. 1.]\n", " [ 1. 1. 1.]]\n" ] } ], "source": [ "b = np.ones((3,3)) # Crea una matriz de unos\n", "print(b)" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[10 10]\n", " [10 10]]\n" ] } ], "source": [ "c = np.full((2, 2), 10, dtype=np.int) # Crea una matriz constante\n", "print(c)" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ 1. 0. 0.]\n", " [ 0. 1. 0.]\n", " [ 0. 0. 1.]]\n" ] } ], "source": [ "d = np.eye(3) # Crea una matriz identidad de 3x3\n", "print(d)" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[3 3 9 9]\n", " [7 0 9 2]\n", " [2 3 8 1]]\n" ] } ], "source": [ "e = np.random.randint(10, size=(3, 4)) #Crea una matriz aleatoria de 3x4\n", "print(e)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Para crear secuencias de números, NumPy proporciona una función análoga a rango que devuelve arrays en lugar de listas:" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[15 20 25 30 35 40 45]\n", "\n", "[ 0. 0.4 0.8 1.2 1.6 2. 2.4 2.8 3.2 3.6]\n" ] } ], "source": [ "import numpy as np\n", "a = np.arange( 15, 50, 5 )\n", "b = np.arange( 0, 4, 0.4 )\n", "print(a)\n", "print(type(a))\n", "print(b)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Cuando arange se utiliza con argumentos de punto flotante, generalmente no es posible predecir el número de elementos obtenidos, debido a la precisión de punto flotante finito. Por esta razón, normalmente es mejor usar la función **linspace** que recibe como argumento el número de elementos que queremos, en lugar del paso:" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[ 0. 0.25 0.5 0.75 1. 1.25 1.5 1.75 2. ]\n" ] }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYYAAAD8CAYAAABzTgP2AAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzt3Xu8lXP6//HX1cnZ5NBUSoopNA7FchpniepnJowZmkFf\nPCSnLwYzCeWYnFKEhMgx569mnCMzGEY7oZLUNFHpiKKipOv3x7X22Du79t6ttde9Du/n47Efe617\n3fda18q2rvU5XR9zd0RERMrVSzoAERHJL0oMIiJSiRKDiIhUosQgIiKVKDGIiEglSgwiIlKJEoOI\niFSixCAiIpUoMYiISCUNkg5gfWy99dbeunXrpMMQESko48ePX+TuTao7ryATQ+vWrSkrK0s6DBGR\ngmJmn9bkPHUliYhIJUoMIiJSiRKDiIhUosQgIiKVKDGIiEglWUkMZjbCzBaY2aS1PG5mdquZTTez\nD81sjwqPdTGzqenH+mQjHhERWX/ZajHcD3RZx+Ndgbbpn17AnQBmVh+4Pf14e6CHmbXPUkwiIrIe\nsrKOwd3/YWat13FKd+ABj31E3zGzxmbWHGgNTHf3GQBmNip97kfZiEtq6dtvYcoUmDYNFi2Cr74C\nM9hgA2jcGNq0ge23h9at47iIFKVcLXBrAcyqcH92+lhVx/ep6gnMrBfR2qBVq1Z1E2WpWbUKxo6F\nl16Cl1+GyZNh9erqr9t6a9h/f+jUCX77W9hmm7qPVURypmBWPrv7cGA4QCqV8oTDKWyffAJ33w0P\nPgjz50OjRnDggXDMMbDrrrDjjtCkCWy5ZbQMvvsOvvgC/vOfaE28/Ta88QY8+yycd15ce+aZkSQa\nNkz63YlIhnKVGOYA21a43zJ9rOFajktdeP99GDAAnnwS6teHo46Cnj2hc2fYZJO1X9ewIWy2WXQh\nHXoo9OoVx6dMgSeegIcegh49oEUL+NOf4KyzYMMNc/KWRCT7cjVddTRwcnp20r7AEnefC4wD2ppZ\nGzNrBJyQPleyac4cOOkk6Ngxuo369IHZs+GZZ+Doo9edFNZl552hXz/4+GN47rloaVx4IbRrB/ff\nX7NuKRHJO9marvoo8Dawo5nNNrPTzKy3mfVOn/I8MAOYDtwNnAXg7quAc4CXgCnA4+4+ORsxCfDD\nD3DTTfFB/cQTcMkl8Omn0Wpo2jR7r1OvHnTrBq++Cq+9Bs2awSmnwMEHR6tCRAqKxUShwpJKpVzV\nVasxfTr8z//AW29B9+5wyy0xqygX3KPFcOGFsHQpXH01XHxxJBARSYyZjXf3VHXn6f/UYvTAA7D7\n7jBpUgwwP/NM7pICxID1KadEa+E3v4muq65dY6BbRPKeEkMxWbkSzjknBpT32isSw4knJrfmoGnT\n6MK66y74xz8iWb31VjKxiEiNKTEUi4UL4bDD4PbbowtnzBho2TLpqCIp9eoF48bB5ptHjA89lHRU\nIrIOSgzF4D//iQVn48fDo4/GgHODPFuisssu8M47EedJJ8Hll8dYhIjkHSWGQjdhAuy3X5SwGDMG\nTjgh6YjWbsst4cUX4bTT4JprYlGcprSK5J08+1optfLuu7E4rXHjKG2x885JR1S9Ro1i1XWTJjBw\nYMxauu8+rZgWySNKDIWqPClsvTW8/jpsu221l+QNM7juuhhz6Ns3ivc99lj+dX+JlCh1JRWicePg\niCMKMylUdMklMHgwPP10TG9Vt5JIXtBXtEIzeXIkhS23jO6jQk0K5c47D5Ytg0svjdIcd96pkt4i\nCVNiKCSzZkGXLlGg7rXXoFjKj/ftC998E2MOm28ON9yQdEQiJU2JoVB89VUkha+/jsVirVsnHVF2\nDRgQ7+3GG+O9nXVW0hGJlCwlhkKwYkWUlpg+PaZ77r570hFlnxncemu0is49N5JDt25JRyVSkjT4\nnO/c49vzm2/CyJGxH0Kxql8fHnkkEt/xx8f+ESKSc0oM+e6222DECLjssvxevJYtm24Kf/tbrM34\n9a9hwYKkIxIpOUoM+WzMmNgRrXt3uPLKpKPJnW22gdGjYzX38cfH3tQikjPZ2qini5lNNbPpZtan\niscvNrP30z+TzOwHM9sy/dhMM5uYfkybLJSbMQN+/3vYaaconV1qexl07AjDhsU6jT4/+ZMSkTqU\n8eCzmdUHbgc6A7OBcWY22t0/Kj/H3W8Ebkyf/2vgAnf/ssLTHOruizKNpWisWBFJwR2efTb2Wy5F\nPXvGYr6bb4a9945/ExGpc9n4Gro3MN3dZ7j7SmAU0H0d5/cAHs3C6xaviy+OSqn33w877JB0NMka\nNAh+9Ss49VRtEyqSI9lIDC2AWRXuz04f+wkz2xjoAjxV4bADY8xsvJn1ykI8he2pp2LA+YILYmyh\n1DVqFJv9bLRRDL5/913SEYkUvVx3XP8aeGuNbqQD3L0D0BU428wOqupCM+tlZmVmVrZw4cJcxJp7\nM2bEN+O9945VwBK22Sam6n74Ifz5z0lHI1L0spEY5gAVC/a0TB+rygms0Y3k7nPSvxcAzxBdUz/h\n7sPdPeXuqSZNmmQcdN5ZtQp69IhB5scei2/K8qNu3eD886M19de/Jh2NSFHLRmIYB7Q1szZm1oj4\n8B+95klm9jPgYODZCsc2MbPNym8DRwCTshBT4RkwIEppDx9efOUusmXgQOjQISqxzlnbdw8RyVTG\nicHdVwHnAC8BU4DH3X2ymfU2s94VTj0GeNndl1U41hR408w+AN4FnnP3FzONqeCMGwdXXQV//CP8\n7ndJR5O/NtgARo2K/RtOOUVbg4rUEfMC/J8rlUp5WVmRLHlYvhz22CNKT0+cGCt+Zd3uvDPKhAwb\nBmeckXQ0IgXDzMa7e6q680ps1VQe+stfYOrUGFxVUqiZ3r3h8MPhwgvhP/9JOhqRoqPEkKQxY2Do\n0BhUPeywpKMpHGZw770xUH/qqdr5TSTLlBiSsmwZnH46tGsXA89SO61awS23RMmM229POhqRoqLE\nkJTLL4eZM+Huu2PxltTeqadC167RHffvfycdjUjRUGJIwrvvwpAhcOaZcFCV6/mkJswisTZoEOMO\nBTiRQiQfKTHk2sqVcNppsZpXq5sz16IFXHddjNc8/HDS0YgUBSWGXLv+epg0KaZcbr550tEUh969\nYd99o77UIhXpFcmUEkMuTZkC11wTxeCOOirpaIpH/fqxYnzx4qhMKyIZUWLIFXc4+2zYeOMYX5Ds\n2nVXuOiiKFX+2mtJRyNS0JQYcuWxx2Ds2Jia+vOfJx1NcerXL/av6N1b5blFMqDEkAtffx17N6dS\n0EtbTtSZjTaKsZtp0+Cmm5KORqRgKTHkwpVXwrx5cMcd0R8udadzZzjuuGiZffZZ0tGIFCQlhro2\ncWKMKZx+Ouy1V9LRlIabb47fF16YbBwiBUqJoS6VDzg3bqyyF7nUqhX07QtPPgmvvpp0NCIFR4mh\nLj38MLzxRixk22qrpKMpLRddBNtvD+eeC99/n3Q0IgVFiaGuLFsWNXz22itq+khubbghDB4ca0eG\nDk06GpGCkpXEYGZdzGyqmU03sz5VPH6ImS0xs/fTP/1qem3BuuEG+Pzz+HCqp/ybiKOOiiJ7/fvH\n4L+I1EjGn1hmVh+4HegKtAd6mFn7Kk59w907pH+uquW1hWXWLLjxxljh/KtfJR1N6TKLgf/vvoPL\nLks6GpGCkY2vsnsD0919hruvBEYB3XNwbf665JIYeFaRvOS1bRvjDCNGwAcfJB2NSEHIRmJoAcyq\ncH92+tiafmVmH5rZC2b2y1peWzjeeScGnS+8ELbbLuloBKK1sMUWMSCt0twi1cpV5/d7QCt33w24\nDfi/2j6BmfUyszIzK1u4cGHWA8wK96jw2awZ9Cme4ZKCt8UWUS5jzBh44YWkoxHJe9lIDHOAbSvc\nb5k+9l/u/rW7L03ffh5oaGZb1+TaCs8x3N1T7p5q0qRJFsKuA6NGRYthwADYdNOko5GKzjwzupUu\nughWrUo6GpG8lo3EMA5oa2ZtzKwRcAIwuuIJZtbMzCx9e+/0635Rk2sLxrffxvTUjh2hZ8+ko5E1\nNWoUM8WmTIF77kk6GpG8lnFicPdVwDnAS8AU4HF3n2xmvc2sd/q044BJZvYBcCtwgocqr800pkTc\ndlvMRho0SNNT81X37rGVar9+UdhQRKpkXoCDcalUysvKypIO40dffhnlnvffH/72t6SjkXUpK4tF\nh336xJagIiXEzMa7e6q68/TVNhsGDoQlS/RBUwhSKTjxRLjllmjhichPKDFk6rPP4NZb4eSTYxcx\nyX/XXBMzyK68MulIRPKSEkOm+veP31ddlWwcUnPbbQdnnQX33ReD0SJSiRJDJiZOhJEj4ZxzotSz\nFI6+fWGTTVQqQ6QKSgyZ6NsXNt88SmBIYWnSJNY0PP00/OtfSUcjkleUGNbXP/4RM5AuuUR7LRSq\nP/0pEkSfPiqVIVKBEsP6cI/FbC1awP/+b9LRyPradFO4/HJ4/XV4+eWkoxHJG0oM6+PZZ6P0xZVX\nwkYbJR2NZOKMM6BNm2j5rV6ddDQieUGJobZWr45vme3aqfRFMWjUCK6+GiZMgMcfTzoakbygxFBb\njz8OkyZFa6FBg6SjkWzo0QN22y1mKGl/aBElhlpZtSrWLeyyC/z+90lHI9lSr15UxP33v2Ntg0iJ\nU2KojYcegk8+ia4HFcorLt26wb77xqroFSuSjkYkUfp0q6mVK6P7aM89o0qnFBezSPizZqkst5Q8\nJYaaGjECZs6Mb5SxtYQUm06doiz3tdfG/hoiJUqJoSa+/Ta+Te6/Pxx5ZNLRSF0xi5pXc+fCsGFJ\nRyOSGCWGmrjrLvj8c7UWSsHBB0fLYeBAWLYs6WhEEpGVxGBmXcxsqplNN7M+VTz+RzP70Mwmmtk/\nzWz3Co/NTB9/38zyaPedtKVLY5+FTp3gkEOSjkZy4eqrYcECGDo06UhEEpFxYjCz+sDtQFegPdDD\nzNqvcdp/gIPdfVfgamD4Go8f6u4darKzUM4NHRofEldfnXQkkiv77Qddu8Ye0doCVEpQNloMewPT\n3X2Gu68ERgGVpu24+z/d/av03XeAlll43bq3ZEl8OHTrFh8WUjquuiq2bL311qQjEcm5bCSGFkDF\nPRJnp4+tzWnACxXuOzDGzMabWa+1XWRmvcyszMzKFi5cmFHANXbLLfDVV9qEpxSlUjEt+eabYfHi\npKMRyamcDj6b2aFEYvhLhcMHuHsHoivqbDM7qKpr3X24u6fcPdWkSZO6D3bxYhg8GI45JtYuSOm5\n8sr4Oxg0KOlIRHIqG4lhDrBthfst08cqMbPdgHuA7u7+Rflxd5+T/r0AeIbomkrekCHRldSvX9KR\nSFJ23x2OOy6+IHzxRfXnixSJbCSGcUBbM2tjZo2AE4DRFU8ws1bA08BJ7v5JheObmNlm5beBI4BJ\nWYgpM0uWxIdB9+7QoUPS0UiSrrgiZqap1SAlJOPE4O6rgHOAl4ApwOPuPtnMeptZ7/Rp/YCtgDvW\nmJbaFHjTzD4A3gWec/cXM40pY7fdFl0Iai3IL38Jv/td/E18+WXS0YjkhHkBbmmYSqW8rKyOljx8\n/TW0bh2rnP/617p5DSkskybBrrtGWW5NW5YCZmbja7IsQCuf1zR0aMxE6t8/6UgkX+yyS4w13Hpr\n/G2IFDklhoq++SamJ3brFtMVRcpdfnm0JgcPTjoSkTqnxFDRHXdEP7LGFmRNu+0WU5eHDNG6Bil6\nSgzlli6Fm26K6qn77JN0NJKP+vWLGWtaDS1FTomh3LBhsGiRxhZk7Tp0iCnMt9wSCUKkSCkxACxf\nDjfeCJ07qyaSrFu/ftGVdNttSUciUmeUGCBaCwsWaGxBqrfHHnDUUbHgTZVXpUgpMSxfHhVUDzsM\nDjgg6WikEPTvH9NWtV+DFCklhrvvhvnzNbYgNZdKxZTmm2+OKc4iRaa0E8N338H118fObAdVWdRV\npGr9+8fU5jvuSDoSkawr7cRw992x8bvGFqS29t4bunSJKc5LlyYdjUhWlW5i+O672PD9wAO1l7Os\nn379YorznXcmHYlIVpVuYhgxAj7/PLoEzJKORgrRfvvFFOcbb4Rly5KORiRrSjMxrFgB110XFVQP\nOyzpaKSQ9e8PCxfGlGeRIlGaieG++2D27OgKUGtBMrH//tCpU7Qali9POhqRrMhKYjCzLmY21cym\nm1mfKh43M7s1/fiHZrZHTa/NupUro7Ww777RDSCSqf79Y8rz8OFJRyKSFRknBjOrD9wOdAXaAz3M\nrP0ap3UF2qZ/egF31uLa7Bo5Ej77TGMLkj3lExiuvx6+/TbpaEQylo0Ww97AdHef4e4rgVFA9zXO\n6Q484OEdoLGZNa/htdnz/fcwYADstVdUURXJlv79Yd48uOeepCMRyVg2EkMLYFaF+7PTx2pyTk2u\nzZ4HHoCZM9VakOw7+OBoOQwcGFOhRbLtiy/giCPgvffq/KUKZvDZzHqZWZmZlS1cuHD9nmTevBgs\n7NYtu8GJmMUXjs8/j6nQItk2eDC88gpssEGdv1Q2EsMcYNsK91umj9XknJpcC4C7D3f3lLunmjRp\nsn6RXnop/P3vai1I3TjssPjicd11MSVaJFsWL44Noo47Dn75yzp/uWwkhnFAWzNrY2aNgBOA0Wuc\nMxo4OT07aV9gibvPreG12VW/fp0+vZQws5gCPXt2TIkWyZYhQ6LM+2WX5eTlMk4M7r4KOAd4CZgC\nPO7uk82st5n1Tp/2PDADmA7cDZy1rmszjUkkMZ07x1To666LqdEimVqyJLqRjj4adt89Jy/ZIBtP\n4u7PEx/+FY8Nq3DbgbNreq1IwSofa+jaNaZGn3560hFJobvttuhKuvzynL1kwQw+ixSMI4+MKdED\nBsQUaZH19c03sVvgr38duwfmiBKDSLaVtxpmzoQHH0w6GilkQ4fGboE53hrAopensKRSKS8rK0s6\nDJG1c49Ww1dfwccfQ8OGSUckhWbpUmjdGvbZB557LitPaWbj3T1V3XlqMYjUhfIZSjNmwCOPJB2N\nFKI77ohFbQlsJKYWg0hdcY9+4aVLYcoUaJCVuR5SCpYtgzZt4u/nxRez9rRqMYgkrbzVMH06PPpo\n0tFIIRk2LPb5SGjbYbUYROrS6tXQsWPUT/roIy2wlOotXw7bbw+77holMLJILQaRfFCvXsw//+QT\neOyxpKORQnD33bG/R0KtBVCLQaTurV4dK1ZXrYJJk9RqkLX77rtoLey4I4wdm/WnV4tBJF+Utxo+\n/hiefDLpaCSf3XMPzJ0b62ASpBaDSC788EP0GderBx9+GL9FKlqxAnbYIVoMdVQFWi0GkXxSv360\nGiZPhqefTjoayUcjRsCcOXmxkZhaDCK58sMPUUu/USN4/321GuRHK1ZA27aw7bbw5pt1lhjUYhDJ\nN/XrRz39iRPh//4v6Wgkn4wcCbNm5UVrAdRiEMmtVaugfXvYeGOYMCEvPgQkYStXQrt20KwZvP12\nnf5NqMUgko8aNIgtZj/4AEbX7WaFUiBGjoRPP411C3nyRSGjxGBmW5rZK2Y2Lf17iyrO2dbMxprZ\nR2Y22czOq/DYFWY2x8zeT/90yyQekYLwxz/G7JMrr4x6SlK6VqyAa66JCqpduyYdzX9l2mLoA7zq\n7m2BV9P317QKuNDd2wP7AmebWfsKj9/i7h3SP9rJTYpfeathwoSslVOWAnXvvfDZZ3DVVXnTWoDM\nE0N3YGT69kjg6DVPcPe57v5e+vY3xN7OLTJ8XZHCduKJUT1TrYbS9d13cO21cMABsVd4Hsk0MTR1\n97np2/OApus62cxaAx2Bf1U4fK6ZfWhmI6rqihIpSg0bQt++UFYGL7yQdDSShOHD4fPP8661ADWY\nlWRmY4BmVTx0KTDS3RtXOPcrd6/yw93MNgX+Dlzr7k+njzUFFgEOXA00d/dT13J9L6AXQKtWrfb8\n9NNPq3lrInlu5cqoibPllpEg8uzDQepQeQXV9u3htddy9rI1nZVU7c4h7n74Ol5kvpk1d/e5ZtYc\nWLCW8xoCTwEPlyeF9HPPr3DO3cDf1hHHcGA4xHTV6uIWyXuNGsW89VNOiXUNxxyTdESSK3feGRVU\nn3gi6UiqlGlX0migZ/p2T+DZNU8wMwPuBaa4+6A1Hmte4e4xwKQM4xEpLCeeGK2Gyy+PldFS/JYu\nhYEDY1zhwAOTjqZKmSaGgUBnM5sGHJ6+j5ltY2blM4z2B04CDqtiWuoNZjbRzD4EDgUuyDAekcLS\noEEMQE+erP0aSsXQobBoUYwt5CmtfBZJ2urV0KEDfPut9oYudl9/HbPR9t03kanKWvksUijq1YOr\nr469oR94IOlopC4NGQJffpnXrQVQYhDJD7/5Dey1V3QrrViRdDRSFxYvhptvhu7dYc89k45mnZQY\nRPKBWZRG+Oyz2MVLis+gQbBkSST/PKfEIJIvymepXHNNzHOX4rFgQSSG446L/b/znBKDSL4obzXM\nmxfz3KV4XHttlMC45pqkI6kRJQaRfHLQQXDEETHP/Ztvko5GsmHmTBg2DE49NdasFAAlBpF8c801\nMc99yJCkI5FsuOKKaA3265d0JDWmxCCSb/baK2au3HhjJAgpXJMmxRTkc8+Fli2TjqbGlBhE8tGA\nAVE6YcCApCORTFx2GWy2GfSpaqua/KXEIJKP2reP4nq33x591FJ43n4bnn0W/vxn2GqrpKOpFSUG\nkXx1xRWxKvqyy5KORGrLHS65BJo2hfPOq/78PKPEIJKvWraE88+Hhx+ObUClcLz8Mvz971E1d9NN\nk46m1lRETySfLV4MO+wAqRS89FLS0UhNrF4dJS+WLIGPP459N/KEiuiJFIPGjeHSS+Mb6JgxSUcj\nNfHgg/D++7GoLY+SQm2oxSCS71asqLwFaD19n8tby5dDu3bQogW8807ebdeqFoNIsdhgg1j0NmEC\njBqVdDSyLoMGwZw5UUU1z5JCbWSUGMxsSzN7xcympX9vsZbzZqZ3anvfzMpqe71IyfvDH6L42qWX\nqix3vpo3L0qZHHssHHBA0tFkJNMWQx/gVXdvC7yavr82h7p7hzWaMbW5XqR01asXK6FnzlSpjHzV\nv38k7YEDk44kY5kmhu7AyPTtkcDROb5epHR07gxHHRXdSvPnJx2NVDRpUuyjcfbZ0LZt0tFkLNPE\n0NTd56ZvzwOaruU8B8aY2Xgz67Ue12NmvcyszMzKFi5cmGHYIgXq5ptjb2gtessvf/4zbL55rFso\nAtUmBjMbY2aTqvjpXvE8j+lNa5vidIC7dwC6Ameb2UFrnlDN9bj7cHdPuXuqSZMm1YUtUpzatYuC\nbPfeq0Vv+eKVV+CFFyJZF1jpi7XJaLqqmU0FDnH3uWbWHHjd3ddZcNzMrgCWuvtN63M9aLqqlLjF\ni+EXv4BddoGxYwt69kvB+/77mBSwYgV89FHMIMtjuZquOhromb7dE3i2ikA2MbPNym8DRwCTanq9\niKyhcWO4+uooufD000lHU9qGDoUpU2Dw4LxPCrWRaYthK+BxoBXwKfB7d//SzLYB7nH3bma2PfBM\n+pIGwCPufu26rq/uddVikJK3ahV07AjLlsU31Q03TDqi0jN/fnTt7b8/PPdcQbTcatpiaJDJi7j7\nF0CnKo5/DnRL354BVLn79dquF5FqNGgQ31IPPxxuuSUqeUpuXXJJTAQYPLggkkJtaOWzSKHq1AmO\nPjqmr372WdLRlJZ//Qvuuw8uuCBaDUVGiUGkkA0eHL/PPz/ZOErJ6tUxM6x586KdNqzEIFLIttsu\n5s4/8ww8/3zS0ZSG+++HcePghhti284ipOqqIoVu5cqYMrlyZazA3WijpCMqXosWwU47RbXbN98s\nuLEFVVcVKRWNGsEdd8CMGUVRpyevXXxxbMBz110FlxRqQ4lBpBgcemhUYL3+epg2LeloitPrr0c3\n0sUXx+LCIqbEIFIsbropFlmdc05sRi/Zs2IFnHEGbL990Q44V6TEIFIsmjeP7SRffjm2l5TsGTgQ\nPvkkuuw23jjpaOqcEoNIMTnrrFiJe/75sXGMZG7qVBgwAHr0gCOPTDqanFBiECkm9epF5dXly2Ou\nvWRm9Wo4/fRoJQwalHQ0OaPEIFJsdtwxdhN78kkV2cvUbbfBG29E2ZFmzZKOJme0jkGkGH3/Peyz\nD3z+eVT/3ELbqdfatGmxPuSww+Cvfy2K6alaxyBSyho2jC6lRYuino/Uzg8/wCmnxBqRIl+zUBUl\nBpFi1bFjVAAdOVJdSrV1663w1lswZAi0aJF0NDmnriSRYrZyJfzqVzBzJkycGFNaZd2mToUOHaKk\n+ejRRdVaUFeSiERXyEMPxSyl007TwrfqrFwZK8g33rgku5DKZZQYzGxLM3vFzKalf/9khMvMdjSz\n9yv8fG1m56cfu8LM5lR4rFsm8YhIFXbaCW68MTasv/POpKPJb5ddBu+9F+Mz22yTdDSJybTF0Ad4\n1d3bAq+m71fi7lPdvYO7dwD2BJbz41afALeUP+7uqhssUhfOOgu6dIELL4xZSvJTY8ZEAu3dOzZA\nKmGZJobuwMj07ZFAdf+anYB/u/unGb6uiNSGWew4tummcPzx0bUkP1q4EE4+GXbeGW6+OeloEpdp\nYmjq7nPTt+cBTas5/wTg0TWOnWtmH5rZiKq6osqZWS8zKzOzsoULF2YQskiJatYMHn449mzQqugf\nrV4NPXvCF1/Ao4+WRC2k6lSbGMxsjJlNquKne8XzPKY3rXVky8waAb8Bnqhw+E5ge6ADMBdYa6p2\n9+HunnL3VJMmTaoLW0SqcsQR0Y8+YkSUkJbYM/uFF2J18+67Jx1NXmhQ3QnufvjaHjOz+WbW3N3n\nmllzYME6nqor8J67z6/w3P+9bWZ3A3+rWdgist7694/dx846C1Kpot9bYJ1efBGuuAJOOgnOPDPp\naPJGpl1Jo4Ge6ds9gWfXcW4P1uhGSieTcscAkzKMR0SqU78+PPII/OxncOyx8NVXSUeUjJkzY2rq\nrrvCsGElOzW1KpkmhoFAZzObBhyevo+ZbWNm/51hZGabAJ2BNZdf3mBmE83sQ+BQQGv3RXKhWTN4\n4on4cDzZ92iwAAAIjklEQVT+eFi1KumIcmv5cvjtb2N84amnNK6whmq7ktbF3b8gZhqtefxzoFuF\n+8uArao476RMXl9EMnDAAfFN+bTTYhrrkCFJR5Qbq1dH19GECbGy+Re/SDqivJNRYhCRAnfqqTB5\ncuw18MtfQq9eSUdU9y69NGpHDRoERx2VdDR5SSUxRErdDTfE4rezz45tQYvZfffFNp1nnBG73EmV\nlBhESl39+jBqVLQYjj0W3n036YjqxvPPR4uoc+fYgEeDzWulxCAiMUPphRfg5z+Hbt2iwmgxeeON\nGGzebbcYdG/YMOmI8poSg4iE5s2jK6l+/VgI99lnSUeUHe+9F2MJrVvHuoWf/SzpiPKeEoOI/OgX\nv4iWw5IlcPDBMZ21kH34IRx5JDRuHElPVRNqRIlBRCrbYw949dUfk8OMGUlHtH7KyuDQQ2GDDaJy\n6rbbJh1RwVBiEJGf2nPPSA5Ll0Zy+PjjpCOqnX/+Ezp1gs03j/GFtm2TjqigKDGISNU6doTXXvtx\ne9A330w6opp55pnYlrNp00gKbdokHVHBUWIQkbXbfXd4++3omz/8cHj88aQjWjv32EuhfPbRm29C\ny5ZJR1WQlBhEZN223z66ZlKpqKvUp0/+1Vb69ls4/XS46KJYizF2bEy9lfWixCAi1dtqqxjAPeMM\nuP76WCQ2f3711+XCJ5/AvvvGPs19+0arZqONko6qoCkxiEjNbLhhFN27/354550oV/3UU8nF4w73\n3BMD5XPmxMrma6+FevpYy5T+BUWkdnr2hHHjoFUrOO646F7KdethxoxotZx+enRxTZgAXbvmNoYi\npsQgIrW3yy4xKH3ttTELqG1bGDAg+vrr0ldfwcUXw847R02nu+6KabVao5BVGSUGM/udmU02s9Vm\nllrHeV3MbKqZTTezPhWOb2lmr5jZtPTvLTKJR0RyqGHD6NOfNCnWDFx6aaycvukm+Prr7L7WggWx\nJekOO8TMoz/8AaZMiaJ46jrKukz/RScBxwL/WNsJZlYfuJ3Y87k90MPM2qcf7gO86u5tgVfT90Wk\nkLRrF62G11+HnXaKb/StWsUeym+9FWMB62PVqihj0bMnbLcdXHUVHHhg1D667z5o0SKrb0N+lOkO\nblMAbN3la/cGprv7jPS5o4DuwEfp34ekzxsJvA78JZOYRCQhBx8c3TplZTB4MIwcGYPV22wTLYpD\nDon1BTvuCJtt9tPrv/wyZhhNmBDTTceOhUWLouhdz55wwQVxrdS5XOzg1gKYVeH+bGCf9O2m7j43\nfXse0DQH8YhIXUql4KGH4JtvoiXx3HNRmO/BB388Z/PN42ejjWDZsjj3m29+fLxlyxhMPvroKAO+\n4Ya5fx8lrNrEYGZjgGZVPHSpuz+brUDc3c1srW1OM+sF9AJo1apVtl5WROrKZpvBySfHz+rV0RqY\nMiXqLs2fH+MQ334Lm2wCm24aA8jt2sWGQW3aaCOdBFWbGNz98AxfYw5QccpAy/QxgPlm1tzd55pZ\nc2DBOuIYDgwHSKVS69lpKSKJqFcvxh922inpSKQGcjGcPw5oa2ZtzKwRcAIwOv3YaKBn+nZPIGst\nEBERWT+ZTlc9xsxmA/sBz5nZS+nj25jZ8wDuvgo4B3gJmAI87u6T008xEOhsZtOAw9P3RUQkQebr\nO5UsQalUysvKypIOQ0SkoJjZeHdf65qzcloZIiIilSgxiIhIJUoMIiJSiRKDiIhUosQgIiKVFOSs\nJDNbCHy6npdvDSzKYjhJKPT3oPiTV+jvodDjh2Tew3bu3qS6kwoyMWTCzMpqMl0rnxX6e1D8ySv0\n91Do8UN+vwd1JYmISCVKDCIiUkkpJobhSQeQBYX+HhR/8gr9PRR6/JDH76HkxhhERGTdSrHFICIi\n61BSicHMupjZVDObbmYFt7+0mY0wswVmNinpWNaHmW1rZmPN7CMzm2xm5yUdU22Y2YZm9q6ZfZCO\n/8qkY1ofZlbfzCaY2d+SjmV9mNlMM5toZu+bWcFV0zSzxmb2pJl9bGZTzGy/pGNaU8l0JZlZfeAT\noDOxveg4oIe7f5RoYLVgZgcBS4EH3H2XpOOprfRmTM3d/T0z2wwYDxxdKP8NLDY338Tdl5pZQ+BN\n4Dx3fyfh0GrFzP4EpIDN3f2opOOpLTObCaTcvSDXMZjZSOANd78nvUfNxu6+OOm4KiqlFsPewHR3\nn+HuK4FRQPeEY6oVd/8H8GXScawvd5/r7u+lb39D7M/RItmoas7D0vTdhumfgvpmZWYtgf8H3JN0\nLKXIzH4GHATcC+DuK/MtKUBpJYYWwKwK92dTQB9KxcbMWgMdgX8lG0ntpLth3ie2oX3F3QsqfmAw\n8GdgddKBZMCBMWY2Pr0XfCFpAywE7kt3591jZpskHdSaSikxSJ4ws02Bp4Dz3f3rpOOpDXf/wd07\nEHuX721mBdOlZ2ZHAQvcfXzSsWTogPR/g67A2eku1kLRANgDuNPdOwLLgLwb7yylxDAH2LbC/Zbp\nY5JD6b75p4CH3f3ppONZX+nm/1igS9Kx1ML+wG/SffSjgMPM7KFkQ6o9d5+T/r0AeIboJi4Us4HZ\nFVqaTxKJIq+UUmIYB7Q1szbpAZ8TgNEJx1RS0oO39wJT3H1Q0vHUlpk1MbPG6dsbERMZPk42qppz\n90vcvaW7tyb+/l9z9xMTDqtWzGyT9MQF0l0wRwAFM0vP3ecBs8xsx/ShTkDeTb5okHQAueLuq8zs\nHOAloD4wwt0nJxxWrZjZo8AhwNZmNhvo7+73JhtVrewPnARMTPfTA/R19+cTjKk2mgMj0zPc6gGP\nu3tBTvksYE2BZ+I7Bg2AR9z9xWRDqrVzgYfTX1BnAKckHM9PlMx0VRERqZlS6koSEZEaUGIQEZFK\nlBhERKQSJQYREalEiUFERCpRYhARkUqUGEREpBIlBhERqeT/A5dLH1ZY4Oy5AAAAAElFTkSuQmCC\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%matplotlib inline\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", "\n", "test = np.linspace( 0, 2, 9 ) # 9 numeros del 0 2 (incluye al 0 y al 2)\n", "print(test)\n", "x = np.linspace( 0, 2*np.pi, 1000 )\n", "f = np.sin(x)\n", "\n", "plt.plot(x,f, 'r')\n", "plt.show()\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ahora porque debemos usar estas funciones arrange en vez de range??? " ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "list" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Creamos una lista con range\n", "lista = list(range(0,100000))\n", "type(lista)" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "100 loops, best of 3: 2.19 ms per loop\n" ] } ], "source": [ "%%timeit\n", "sum(lista)" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# Ahora lo creamos con arange\n", "array = np.arange(0, 100000)" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "10000 loops, best of 3: 64 µs per loop\n" ] } ], "source": [ "%%timeit\n", "np.sum(array)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Como ves, las mejoras en este caso son de 2 órdenes de magnitud. NumPy nos ofrece funciones que se ejecutan prácticamente en tiempos de lenguaje compilado (Fortran, C, C++) y optimizado, pero escribiendo mucho menos código y con un nivel de abstracción mayor." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Indexación de matrices\n", "Numpy ofrece varias formas de indexar en arreglos.\n", "\n", "**Slicing:** Similar a las listas de Python, matrices numpy se pueden cortar. Dado que los arrays pueden ser multidimensionales, debe especificar una división para cada dimensión de la matriz:" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[2 3]\n", " [6 7]]\n" ] } ], "source": [ "import numpy as np\n", "\n", "# Crea una array con forma (3,4)\n", "# [[ 1 2 3 4]\n", "# [ 5 6 7 8]\n", "# [ 9 10 11 12]]\n", "\n", "a = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])\n", "\n", "# Usaremos slicing para obtener el subarray de 2 filas\n", "# y las columnas 1 y 2; b sera un array de (2,2):\n", "# [[2 3]\n", "# [6 7]]\n", "\n", "b = a[:2, 1:3]\n", "print(b)" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2\n", "77\n" ] } ], "source": [ "# Una porción de una matriz es una vista de los mismos datos\n", "# por lo que la modificación modificará la matriz original.\n", "print(a[0, 1]) # Imprimirá \"2\"\n", "b[0, 0] = 77 # b[0, 0] es la misma data de a[0, 1]\n", "print(a[0, 1]) # Imprimirá \"77\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "También puede mezclar índices enteros con indexación de sectores. Sin embargo, al hacerlo, se obtendrá una matriz de rango inferior a la matriz original." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![Alt text](../images/matrizslice.png \"Optional title\")" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[5 6 7 8] (4,)\n", "[[5 6 7 8]] (1, 4)\n" ] } ], "source": [ "import numpy as np\n", "\n", "# Crea una array con forma (3,4)\n", "# [[ 1 2 3 4]\n", "# [ 5 6 7 8]\n", "# [ 9 10 11 12]]\n", "\n", "a = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])\n", "\n", "# Dos maneras de acceder a la data en el medio de las filas del array\n", "# La mezcla de índices de indexación con slicing produce una matriz de menor rango,\n", "# Mientras que el uso de sólo slicing produce una matriz del mismo rango que el array original\n", "\n", "fila_f1 = a[1, :] # Vista de la segunda fila de A de Rango 1\n", "fila_f2 = a[1:2, :] # Vista de la segunda fila de A de Rango 2\n", "print(fila_f1, fila_f1.shape) # Imprimirá \"[5 6 7 8] (4,)\"\n", "print(fila_f2, fila_f2.shape) # Imprimirá \"[[5 6 7 8]] (1, 4)\"" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[ 2 6 10] (3,)\n", "[[ 2]\n", " [ 6]\n", " [10]] (3, 1)\n" ] } ], "source": [ "# Podemos hacer la misma distincion cuando accedemos a las columnas de un array\n", "col_r1 = a[:, 1]\n", "col_r2 = a[:, 1:2]\n", "print(col_r1, col_r1.shape) # Prints \"[ 2 6 10] (3,)\"\n", "print(col_r2, col_r2.shape) # Prints \"[[ 2]\n", " # [ 6]\n", " # [10]] (3, 1)\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Indexación de matrices de números enteros**: Cuando indexa matrices numpy utilizando slicing, la vista de array resultante siempre será un subarray de la matriz original. Por el contrario, la indexación de matriz de números enteros le permite construir arrays arbitrarios utilizando los datos de otra matriz. Aquí hay un ejemplo:" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1 4 5]\n" ] } ], "source": [ "import numpy as np\n", "\n", "a = np.array([[1,2], [3, 4], [5, 6]])\n", "\n", "# Un ejemplo de indexacion de matrices de enteros\n", "# El array retornado tendrá forma (3,) y\n", "print(a[[0, 1, 2], [0, 1, 0]]) # Impimirá \"[1 4 5]\"" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1 4 5]\n" ] } ], "source": [ "# El ejemplo anterior de indexacion de matriz de números enteros es equivalente a esto:\n", "print(np.array([a[0, 0], a[1, 1], a[2, 0]])) # Impimirá \"[1 4 5]\"" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[2 2]\n" ] } ], "source": [ "# Cuando utilice la indexacion de matriz de números enteros, puede reutilizar el mismo elemento de la matriz de origen:\n", "print(a[[0, 0], [1, 1]]) # Impimirá \"[2 2]\"" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[2 2]\n" ] } ], "source": [ "# Equivalente al ejemplo anterior de indexacion de matriz de números enteros\n", "print(np.array([a[0, 1], a[0, 1]])) # Impimirá \"[2 2]\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Un truco útil con la indexacion de matriz de números enteros es la selección o mutación de un elemento de cada fila de una matriz:" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ 1 2 3]\n", " [ 4 5 6]\n", " [ 7 8 9]\n", " [10 11 12]]\n" ] } ], "source": [ "import numpy as np\n", "\n", "# Crear una nueva matriz a partir de la cual seleccionaremos elementos\n", "a = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])\n", "\n", "print (a)" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[ 1 6 7 11]\n" ] } ], "source": [ "# Crear una matriz de índices\n", "b = np.array([0, 2, 0, 1])\n", "\n", "# Selecciona un elemento de cada fila de a usando los índices en b\n", "print(a[np.arange(4), b]) # Prints \"[ 1 6 7 11]\"" ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[11 2 3]\n", " [ 4 5 16]\n", " [17 8 9]\n", " [10 21 12]]\n" ] } ], "source": [ "# Muta un elemento de cada fila de a usando los índices en b\n", "a[np.arange(4), b] += 10\n", "\n", "print (a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Datatypes\n", "\n", "Cada matriz numpy es una cuadrícula de elementos del mismo tipo. Numpy proporciona un gran conjunto de tipos de datos numéricos que puede utilizar para construir matrices. Numpy intenta adivinar un tipo de datos cuando se crea una matriz, pero las funciones que construyen arrays generalmente también incluyen un argumento opcional para especificar explícitamente el tipo de datos. Aquí hay un ejemplo:" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "int32\n" ] } ], "source": [ "x = np.array([1, 2]) \n", "print(x.dtype) " ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "float64\n" ] } ], "source": [ "x = np.array([1.0, 2.0]) \n", "print(x.dtype) " ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "int64\n" ] } ], "source": [ "x = np.array([1, 2], dtype=np.int64) \n", "print (x.dtype) " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Operaciones Matemáticas en arrays\n", "\n", "Las funciones matemáticas básicas funcionan de manera **elementwise** en arrays, y están disponibles como sobrecargas del operador y como funciones en el módulo numpy:" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "El array X es:\n", "[[ 1. 2.]\n", " [ 3. 4.]]\n", "\n", "El array Y es:\n", "[[ 5. 6.]\n", " [ 7. 8.]]\n", "\n", "[[ 6. 8.]\n", " [ 10. 12.]]\n", "\n", "[[ 6. 8.]\n", " [ 10. 12.]]\n" ] } ], "source": [ "import numpy as np\n", "\n", "x = np.array([[1,2],[3,4]], dtype=np.float64)\n", "y = np.array([[5,6],[7,8]], dtype=np.float64)\n", "\n", "print(\"El array X es:\")\n", "print(x)\n", "print()\n", "\n", "print(\"El array Y es:\")\n", "print(y)\n", "print()\n", "\n", "print(x + y)\n", "print()\n", "print(np.add(x, y))" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[-4. -4.]\n", " [-4. -4.]]\n", "\n", "[[-4. -4.]\n", " [-4. -4.]]\n" ] } ], "source": [ "print(x - y)\n", "print()\n", "print(np.subtract(x, y))" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ 5. 12.]\n", " [ 21. 32.]]\n", "\n", "[[ 5. 12.]\n", " [ 21. 32.]]\n" ] } ], "source": [ "print(x * y)\n", "print()\n", "print(np.multiply(x, y))" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ 0.2 0.33333333]\n", " [ 0.42857143 0.5 ]]\n", "\n", "[[ 0.2 0.33333333]\n", " [ 0.42857143 0.5 ]]\n" ] } ], "source": [ "print(x / y)\n", "print()\n", "print(np.divide(x, y))" ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ 1. 1.41421356]\n", " [ 1.73205081 2. ]]\n" ] } ], "source": [ "print(np.sqrt(x))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Tenga en cuenta que a diferencia de MATLAB, ** * ** es multiplicación elemental, no multiplicación matricial. Utilizamos la función de punto para calcular productos internos de vectores, multiplicar un vector por una matriz y multiplicar matrices. **Dot** está disponible tanto como una función en el módulo numpy como un método de instancia de objetos de matriz:" ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "219\n", "219\n" ] } ], "source": [ "import numpy as np\n", "\n", "x = np.array([[1,2],[3,4]])\n", "y = np.array([[5,6],[7,8]])\n", "\n", "v = np.array([9,10])\n", "w = np.array([11, 12])\n", "\n", "# Producto interno de vectores\n", "print(v.dot(w))\n", "print(np.dot(v, w))" ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[29 67]\n", "[29 67]\n" ] } ], "source": [ "# Producto de matrices por vectores \n", "print(x.dot(v))\n", "print(np.dot(x, v))" ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[19 22]\n", " [43 50]]\n", "[[19 22]\n", " [43 50]]\n" ] } ], "source": [ "# Multiplicacion de matrices \n", "print(x.dot(y))\n", "print(np.dot(x, y))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Numpy proporciona muchas funciones útiles para realizar cálculos en matrices; Uno de los más útiles es **sum**:" ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[1 2]\n", " [3 4]]\n", "\n", "10\n", "\n", "[4 6]\n", "\n", "[3 7]\n" ] } ], "source": [ "import numpy as np\n", "\n", "x = np.array([[1,2],[3,4]])\n", "print(x)\n", "print()\n", "print (np.sum(x)) # Halla la suma de todos los elementos\n", "print()\n", "print (np.sum(x, axis=0)) # Halla la suma de cada columna\n", "print()\n", "print (np.sum(x, axis=1)) # Halla la suma de cada fila" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Si desea más información acerca de las funciones matemáticas que provee numpy visite:\n", "\n", "https://docs.scipy.org/doc/numpy/reference/routines.math.html" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Aparte de calcular funciones matemáticas usando matrices, con frecuencia necesitamos cambiar la forma o de otra manera manipular datos en matrices. El ejemplo más simple de este tipo de operación es la transpuesta de una matriz; Para transponer una matriz, simplemente use el atributo **T** de un objeto de matriz:" ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[1 2]\n", " [3 4]]\n", "\n", "[[1 3]\n", " [2 4]]\n" ] } ], "source": [ "import numpy as np\n", "\n", "x = np.array([[1,2], [3,4]])\n", "print(x) \n", "print()\n", "print(x.T)" ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1 2 3]\n", "[1 2 3]\n" ] } ], "source": [ "# Que pasará si hacemos la transpuesta de una matriz de rango 1\n", "v = np.array([1,2,3])\n", "print(v)\n", "print(v.T) " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Reshape\n", "\n", "Con np.arange() es posible crear \"vectores\" cuyos elementos tomen valores consecutivos o equiespaciados, como hemos visto anteriormente. ¿Podemos hacer lo mismo con \"matrices\"? Pues sí, pero no usando una sola función. Imagina que quieres crear algo como esto:\n", "\n", "$$\n", "\\left(\\begin{array}{ccc} \n", "10 & 20 & 30\\\\\n", "40 & 50 & 60\\\\\n", "70 & 80 & 90\\\\\n", "\\end{array}\\right)\n", "$$ \n", "\n", "* Comenzaremos por crear un array 1d con los valores (10,20,30,40...) usando np.arange().\n", "* Luego le daremos forma de array 2d. con np.reshape(array, (dim0, dim1))." ] }, { "cell_type": "code", "execution_count": 44, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[10 20 30 40 50 60 70 80 90]\n", "\n", "[[10 20 30]\n", " [40 50 60]\n", " [70 80 90]]\n" ] } ], "source": [ "a = np.arange(10,100,10)\n", "print(a)\n", "print()\n", "\n", "M = np.reshape(a, [3, 3])\n", "print(M)" ] }, { "cell_type": "code", "execution_count": 45, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(3, 3)" ] }, "execution_count": 45, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.shape(M)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ahora veamos algo interesante:" ] }, { "cell_type": "code", "execution_count": 46, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])" ] }, "execution_count": 46, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a = np.arange(12)\n", "a" ] }, { "cell_type": "code", "execution_count": 47, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(12,)" ] }, "execution_count": 47, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.shape(a)" ] }, { "cell_type": "code", "execution_count": 48, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]])" ] }, "execution_count": 48, "metadata": {}, "output_type": "execute_result" } ], "source": [ "b = np.reshape(a,[1,12])\n", "b" ] }, { "cell_type": "code", "execution_count": 49, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(1, 12)" ] }, "execution_count": 49, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.shape(b) # ahora b tiene una dimensión más " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Broadcasting\n", "\n", "**Broadcasting** es un potente mecanismo que permite a numpy trabajar con matrices de diferentes formas al realizar operaciones aritméticas. Con frecuencia tenemos una matriz más pequeña y una matriz más grande, y queremos usar la matriz más pequeña varias veces para realizar alguna operación en la matriz más grande. \n", "\n", "![Alt text](../images/numpy_broadcasting.png \"Optional title\")\n", "\n", "Por ejemplo, supongamos que queremos añadir un vector constante a cada fila de una matriz. Podríamos hacerlo así:" ] }, { "cell_type": "code", "execution_count": 50, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ 2 2 4]\n", " [ 5 5 7]\n", " [ 8 8 10]\n", " [11 11 13]]\n" ] } ], "source": [ "import numpy as np\n", "\n", "# Vamos a añadir el vector V a cada fila de la matriz x\n", "# guardando el resultado en la matriz y\n", "\n", "x = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])\n", "v = np.array([1, 0, 1])\n", "y = np.empty_like(x) # Creamos una matriz vacia de la misma forma de X\n", "\n", "# Añadimos el vector v a cada fila de la matriz X con un loop\n", "\n", "for i in range(4):\n", " y[i, :] = x[i, :] + v\n", "\n", "print(y)\n" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "Esto funciona; Sin embargo, cuando la matriz x es muy grande, el cálculo de un bucle explícito en Python podría ser lento. Obsérvese que la adición del vector v a cada fila de la matriz x es equivalente a formar una matriz vv apilando múltiples copias de v verticalmente, realizando entonces la suma elemental de x y vv. Podríamos implementar este enfoque como este:\n" ] }, { "cell_type": "code", "execution_count": 51, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[1 0 1]\n", " [1 0 1]\n", " [1 0 1]\n", " [1 0 1]]\n", "[[ 2 2 4]\n", " [ 5 5 7]\n", " [ 8 8 10]\n", " [11 11 13]]\n" ] } ], "source": [ "import numpy as np\n", "\n", "# Vamos a añadir el vector V a cada fila de la matriz x\n", "# guardando el resultado en la matriz y\n", "\n", "x = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])\n", "v = np.array([1, 0, 1])\n", "vv = np.tile(v, (4, 1)) # Apila 4 copias de v una encima de la otra\n", "print (vv) \n", "\n", "y = x + vv \n", "print(y)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Numpy Broadcasting nos permite realizar este cálculo sin realmente crear múltiples copias de v. Considere esta versión, utilizando la Broadcasting:" ] }, { "cell_type": "code", "execution_count": 52, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ 2 2 4]\n", " [ 5 5 7]\n", " [ 8 8 10]\n", " [11 11 13]]\n" ] } ], "source": [ "import numpy as np\n", "\n", "# Vamos a añadir el vector V a cada fila de la matriz x\n", "# guardando el resultado en la matriz y\n", "\n", "x = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])\n", "v = np.array([1, 0, 1])\n", "y = x + v # Añada v a cada fila de x mediante broadcasting\n", "print(y)" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "### Fancy indexing\n", "\n", "**Fancy indexing** es cuando se utiliza una matriz o lista en lugar de un índice:" ] }, { "cell_type": "code", "execution_count": 53, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[10, 11, 12, 13, 14],\n", " [20, 21, 22, 23, 24],\n", " [30, 31, 32, 33, 34]])" ] }, "execution_count": 53, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A = np.array([[n+m*10 for n in range(5)] for m in range(5)])\n", "\n", "row_indices = [1, 2, 3]\n", "A[row_indices]" ] }, { "cell_type": "code", "execution_count": 54, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([11, 22, 34])" ] }, "execution_count": 54, "metadata": {}, "output_type": "execute_result" } ], "source": [ "col_indices = [1, 2, -1] # remember, index -1 means the last element\n", "A[row_indices, col_indices]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Transformaciones Array/Matrix \n", "\n", "Arriba hemos utilizado el .T para transponer la matriz v. También podríamos haber utilizado la función de transposición para lograr la misma cosa. \n", "\n", "Otras funciones matemáticas que transforman objetos matriciales son:" ] }, { "cell_type": "code", "execution_count": 55, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "matrix([[ 0.+1.j, 0.+2.j],\n", " [ 0.+3.j, 0.+4.j]])" ] }, "execution_count": 55, "metadata": {}, "output_type": "execute_result" } ], "source": [ "C = np.matrix([[1j, 2j], [3j, 4j]])\n", "C" ] }, { "cell_type": "code", "execution_count": 56, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "matrix([[ 0.-1.j, 0.-2.j],\n", " [ 0.-3.j, 0.-4.j]])" ] }, "execution_count": 56, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.conjugate(C)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Conjugado hermitiano: transpuesta + conjugada" ] }, { "cell_type": "code", "execution_count": 57, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "matrix([[ 0.-1.j, 0.-3.j],\n", " [ 0.-2.j, 0.-4.j]])" ] }, "execution_count": 57, "metadata": {}, "output_type": "execute_result" } ], "source": [ "C.H" ] }, { "cell_type": "code", "execution_count": 58, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "matrix([[ 0., 0.],\n", " [ 0., 0.]])" ] }, "execution_count": 58, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.real(C)" ] }, { "cell_type": "code", "execution_count": 59, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "matrix([[ 1., 2.],\n", " [ 3., 4.]])" ] }, "execution_count": 59, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.imag(C)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Para obtener el angulo o argumento" ] }, { "cell_type": "code", "execution_count": 60, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[ 1.57079633, 1.57079633],\n", " [ 1.57079633, 1.57079633]])" ] }, "execution_count": 60, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.angle(C)" ] }, { "cell_type": "code", "execution_count": 61, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "matrix([[ 1., 2.],\n", " [ 3., 4.]])" ] }, "execution_count": 61, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.abs(C)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Ahora veamos algo de Algebra lineal\n", "\n", "El paquete de álgebra lineal en NumPy se llama linalg, así que importando NumPy con la convención habitual podemos acceder a él escribiendo np.linalg. Si imprimimos la ayuda del paquete vemos que tenemos funciones para:\n", "\n", "- Funciones básicas (norma de un vector, inversa de una matriz, determinante, traza)\n", "- Resolución de sistemas\n", "- Autovalores y autovectores\n", "- Descomposiciones matriciales (QR, SVD)\n", "- Pseudoinversas" ] }, { "cell_type": "code", "execution_count": 62, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on package numpy.linalg in numpy:\n", "\n", "NAME\n", " numpy.linalg\n", "\n", "DESCRIPTION\n", " Core Linear Algebra Tools\n", " -------------------------\n", " Linear algebra basics:\n", " \n", " - norm Vector or matrix norm\n", " - inv Inverse of a square matrix\n", " - solve Solve a linear system of equations\n", " - det Determinant of a square matrix\n", " - lstsq Solve linear least-squares problem\n", " - pinv Pseudo-inverse (Moore-Penrose) calculated using a singular\n", " value decomposition\n", " - matrix_power Integer power of a square matrix\n", " \n", " Eigenvalues and decompositions:\n", " \n", " - eig Eigenvalues and vectors of a square matrix\n", " - eigh Eigenvalues and eigenvectors of a Hermitian matrix\n", " - eigvals Eigenvalues of a square matrix\n", " - eigvalsh Eigenvalues of a Hermitian matrix\n", " - qr QR decomposition of a matrix\n", " - svd Singular value decomposition of a matrix\n", " - cholesky Cholesky decomposition of a matrix\n", " \n", " Tensor operations:\n", " \n", " - tensorsolve Solve a linear tensor equation\n", " - tensorinv Calculate an inverse of a tensor\n", " \n", " Exceptions:\n", " \n", " - LinAlgError Indicates a failed linear algebra operation\n", "\n", "PACKAGE CONTENTS\n", " _umath_linalg\n", " info\n", " lapack_lite\n", " linalg\n", " setup\n", "\n", "DATA\n", " absolute_import = _Feature((2, 5, 0, 'alpha', 1), (3, 0, 0, 'alpha', 0...\n", " division = _Feature((2, 2, 0, 'alpha', 2), (3, 0, 0, 'alpha', 0), 8192...\n", " print_function = _Feature((2, 6, 0, 'alpha', 2), (3, 0, 0, 'alpha', 0)...\n", "\n", "FILE\n", " c:\\users\\gerson\\anaconda3\\lib\\site-packages\\numpy\\linalg\\__init__.py\n", "\n", "\n" ] } ], "source": [ "help(np.linalg)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Determinante de una matriz" ] }, { "cell_type": "code", "execution_count": 63, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "3.0000000000000004" ] }, "execution_count": 63, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A = np.array([[2,0,1],[3,0,0],[5,1,1]])\n", "np.linalg.det(A)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Inversa de una matriz" ] }, { "cell_type": "code", "execution_count": 64, "metadata": { "scrolled": true }, "outputs": [ { "data": { "text/plain": [ "array([[ 0. , 0.33333333, 0. ],\n", " [-1. , -1. , 1. ],\n", " [ 1. , -0.66666667, 0. ]])" ] }, "execution_count": 64, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A = np.array([[2,0,1],[3,0,0],[5,1,1]])\n", "np.linalg.inv(A)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "En la versión 3.5 de Python se incorporó un nuevo operador @ para poder calcular hacer multiplicaciones de matrices de una forma más legible" ] }, { "cell_type": "code", "execution_count": 65, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([23, 67, 66, 49])" ] }, "execution_count": 65, "metadata": {}, "output_type": "execute_result" } ], "source": [ "mat = np.array([[1, 5, 8, 5],\n", " [0, 6, 4, 2],\n", " [9, 3, 1, 6]])\n", "\n", "vec1 = np.array([5, 6, 2])\n", "\n", "vec1 @ mat" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Copy y \"deep copy\"\n", "\n", "\n", "Para lograr un alto rendimiento, las asignaciones en Python usualmente no copian los objetos subyacentes. Esto es importante por ejemplo cuando se pasan objetos entre funciones, para evitar una cantidad excesiva de copias de memoria cuando no es necesario (término técnico: pasar por referencia)." ] }, { "cell_type": "code", "execution_count": 66, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[1, 2],\n", " [3, 4]])" ] }, "execution_count": 66, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A = np.array([[1, 2], [3, 4]])\n", "\n", "A" ] }, { "cell_type": "code", "execution_count": 67, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# Ahora B esta referenciando al mismo array que A\n", "B = A " ] }, { "cell_type": "code", "execution_count": 68, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[10, 2],\n", " [ 3, 4]])" ] }, "execution_count": 68, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Los cambios que apliquemos a B afectarán a A\n", "B[0,0] = 10\n", "\n", "B" ] }, { "cell_type": "code", "execution_count": 69, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[10, 2],\n", " [ 3, 4]])" ] }, "execution_count": 69, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Si queremos evitar este comportamiento, para que cuando obtengamos un nuevo objeto completamente independiente B, copiado de A, entonces necesitamos hacer una llamada \"copia profunda\" usando la función copy al igual que hicimos con las listas:" ] }, { "cell_type": "code", "execution_count": 70, "metadata": { "collapsed": true }, "outputs": [], "source": [ "B = np.copy(A)" ] }, { "cell_type": "code", "execution_count": 71, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[5, 2],\n", " [3, 4]])" ] }, "execution_count": 71, "metadata": {}, "output_type": "execute_result" } ], "source": [ "B[0,0] = 5\n", "B" ] }, { "cell_type": "code", "execution_count": 72, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[10, 2],\n", " [ 3, 4]])" ] }, "execution_count": 72, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Iterando sobre los elementos del array\n", "\n", "Generalmente, queremos evitar iterar sobre los elementos de arrays cada vez que podemos (a toda costa). La razón es que en un lenguaje interpretado como Python (o MATLAB), las iteraciones son realmente lentas en comparación con las operaciones vectorizadas.\n", "\n", "Sin embargo, a veces las iteraciones son inevitables. Para estos casos, el Python for loop es la forma más conveniente de iterar sobre una matriz:" ] }, { "cell_type": "code", "execution_count": 73, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n", "2\n", "3\n", "4\n" ] } ], "source": [ "v = np.array([1,2,3,4])\n", "\n", "for element in v:\n", " print(element)" ] }, { "cell_type": "code", "execution_count": 74, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "fila [1 2]\n", "1\n", "2\n", "fila [3 4]\n", "3\n", "4\n" ] } ], "source": [ "M = np.array([[1,2], [3,4]])\n", "\n", "for row in M:\n", " print(\"fila\", row)\n", " \n", " for element in row:\n", " print(element)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Cuando necesitamos iterar sobre cada elemento de una matriz y modificar sus elementos, es conveniente utilizar la función enumerate para obtener tanto el elemento como su índice en el bucle for:" ] }, { "cell_type": "code", "execution_count": 75, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "row_idx 0 row [1 2]\n", "col_idx 0 element 1\n", "col_idx 1 element 2\n", "row_idx 1 row [3 4]\n", "col_idx 0 element 3\n", "col_idx 1 element 4\n" ] } ], "source": [ "for row_idx, row in enumerate(M):\n", " print(\"row_idx\", row_idx, \"row\", row)\n", " \n", " for col_idx, element in enumerate(row):\n", " print(\"col_idx\", col_idx, \"element\", element)\n", " \n", " # update the matrix M: square each element\n", " M[row_idx, col_idx] = element ** 2" ] }, { "cell_type": "code", "execution_count": 76, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[ 1, 4],\n", " [ 9, 16]])" ] }, "execution_count": 76, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# each element in M is now squared\n", "M" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Funciones Vectorizadas\n", "\n", "Como se mencionó en varias ocasiones a estas alturas, para obtener un buen rendimiento deberíamos tratar de evitar el bucle de elementos en nuestros vectores y matrices, y en su lugar utilizar algoritmos vectorizados. El primer paso en la conversión de un algoritmo escalar a un algoritmo vectorizado es asegurarse de que las funciones que escribimos trabajan con entradas vectoriales." ] }, { "cell_type": "code", "execution_count": 77, "metadata": {}, "outputs": [ { "ename": "ValueError", "evalue": "The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 8\u001b[0m \u001b[1;32mreturn\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m---> 10\u001b[0;31m \u001b[0mTheta\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0marray\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m-\u001b[0m\u001b[1;36m2\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;36m3\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m-\u001b[0m\u001b[1;36m4\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;32m\u001b[0m in \u001b[0;36mTheta\u001b[0;34m(x)\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0mScalar\u001b[0m \u001b[0mimplemenation\u001b[0m \u001b[0mof\u001b[0m \u001b[0mthe\u001b[0m \u001b[0mHeaviside\u001b[0m \u001b[0mstep\u001b[0m \u001b[0mfunction\u001b[0m\u001b[1;33m.\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \"\"\"\n\u001b[0;32m----> 5\u001b[0;31m \u001b[1;32mif\u001b[0m \u001b[0mx\u001b[0m \u001b[1;33m>=\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 6\u001b[0m \u001b[1;32mreturn\u001b[0m \u001b[1;36m1\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 7\u001b[0m \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", "\u001b[0;31mValueError\u001b[0m: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()" ] } ], "source": [ "def Theta(x):\n", " \"\"\"\n", " Scalar implemenation of the Heaviside step function.\n", " \"\"\"\n", " if x >= 0:\n", " return 1\n", " else:\n", " return 0\n", " \n", "Theta(np.array([[1,-2,3,-4]]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Eso no funcionó porque no escribimos la función Theta para que pueda manejar una entrada vectorial ...\n", "\n", "Para obtener una versión vectorizada de Theta podemos usar la función Numpy **vectorize**. En muchos casos puede vectorizar automáticamente una función:" ] }, { "cell_type": "code", "execution_count": 78, "metadata": {}, "outputs": [], "source": [ "Theta_vec = np.vectorize(Theta)" ] }, { "cell_type": "code", "execution_count": 79, "metadata": { "scrolled": false }, "outputs": [ { "data": { "text/plain": [ "array([[1, 0, 1, 0]])" ] }, "execution_count": 79, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Theta_vec(np.array([[1,-2,3,-4]]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Otro ejemplo:" ] }, { "cell_type": "code", "execution_count": 80, "metadata": {}, "outputs": [ { "ename": "ValueError", "evalue": "The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 8\u001b[0m \u001b[0mA\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0marray\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;36m2\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;36m3\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;36m4\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m---> 10\u001b[0;31m \u001b[0mmyfunc\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mA\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m2\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;32m\u001b[0m in \u001b[0;36mmyfunc\u001b[0;34m(a, b)\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0mmyfunc\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0ma\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mb\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[1;34m\"Retorna a-b si a>b, en otro caso retorna a+b\"\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[1;32mif\u001b[0m \u001b[0ma\u001b[0m \u001b[1;33m>\u001b[0m \u001b[0mb\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 4\u001b[0m \u001b[1;32mreturn\u001b[0m \u001b[0ma\u001b[0m \u001b[1;33m-\u001b[0m \u001b[0mb\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", "\u001b[0;31mValueError\u001b[0m: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()" ] } ], "source": [ "def myfunc(a, b):\n", " \"Retorna a-b si a>b, en otro caso retorna a+b\"\n", " if a > b:\n", " return a - b\n", " else:\n", " return a + b\n", "\n", "A = np.array([1,2,3,4]) \n", "\n", "myfunc(A, 2)" ] }, { "cell_type": "code", "execution_count": 81, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([3, 4, 1, 2])" ] }, "execution_count": 81, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Vectorizando \n", "\n", "def myfunc(a, b):\n", " \"Retorna a-b si a>b, en otro caso retorna a+b\"\n", " if a > b:\n", " return a - b\n", " else:\n", " return a + b\n", "\n", "A = np.array([1,2,3,4]) \n", "\n", "vfunc = np.vectorize(myfunc)\n", "\n", "vfunc(A, 2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Veamos algunas aplicaciones" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Resolver el siguiente sistema: \n", "\n", "$$\n", "\\left(\\begin{array}{ccc} \n", "2 & 0 & 1\\\\\n", "3 & 0 & 0\\\\\n", "5 & 1 & 1\\\\\n", "\\end{array}\\right)\n", "\\left(\\begin{array}{ccc} \n", "1 & 0 & 1\\\\\n", "1 & 2 & 1\\\\\n", "1 & 1 & 0\\\\\n", "\\end{array}\\right)\n", "\\left(\\begin{array}{c} \n", "x \\\\\n", "y \\\\\n", "z \\\\\n", "\\end{array}\\right)\n", "=\n", "\\left(\\begin{array}{ccc} \n", "21 \\\\\n", "15 \\\\\n", "30 \\\\\n", "\\end{array}\\right)\n", "$$ " ] }, { "cell_type": "code", "execution_count": 82, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[3 1 2]\n", " [3 0 3]\n", " [7 2 7]]\n" ] } ], "source": [ "M = (np.array([[2, 0, 1],\n", " [3, 0, 0],\n", " [5, 1, 1]])\n", " @\n", " np.array([[1, 0, 1],\n", " [1, 1, 2],\n", " [1, 1, 0]]))\n", "print(M)" ] }, { "cell_type": "code", "execution_count": 83, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([ 13.5, -2.5, -8.5])" ] }, "execution_count": 83, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x = np.linalg.solve(M, np.array([21, 15, 30]))\n", "x" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Ejercicios:\n", "\n", "Sean las matrices:\n", "\n", "\n", "$$ B = \n", "\\left(\\begin{array}{ccc} \n", "1 & 2 & -3\\\\\n", "3 & 4 & -1\\\\\n", "\\end{array}\\right)\n", ", A= \n", "\\left(\\begin{array}{ccc} \n", "2 & -5 & 1\\\\\n", "1 & 4 & 5\\\\\n", "2 & -1 & 6\\\\\n", "\\end{array}\\right)\n", ",y =\n", "\\left(\\begin{array}{c} \n", "2 \\\\\n", "-4 \\\\\n", "1 \\\\\n", "\\end{array}\\right)\n", ",z=\n", "\\left(\\begin{array}{ccc} \n", "-15 \\\\\n", "-8 \\\\\n", "-22 \\\\\n", "\\end{array}\\right)\n", "$$\n", "\n", "Calcule e imprima cada una de las siguientes operaciones:\n", "\n", "* $BA$ \n", "\n", "\n", "* $AB^T$\n", "\n", "\n", "* $Ay$\n", "\n", "\n", "* $y^{T}z$ (Este es el producto interno, o producto de punto, de y & z.)\n", "\n", "\n", "* $yz^T$ (Este es el producto tensorial de y & z.)\n" ] }, { "cell_type": "code", "execution_count": 84, "metadata": {}, "outputs": [ { "data": { "text/html": [ "/* This template is inspired in the one used by Lorena Barba\n", "in the numerical-mooc repository: https://github.com/numerical-mooc/numerical-mooc\n", "We thank her work and hope you also enjoy the look of the notobooks with this style */\n", "\n", "\n", "Estilo aplicado\n", "\n", "\n" ], "text/plain": [ "" ] }, "execution_count": 84, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Esta celda da el estilo al notebook\n", "from IPython.core.display import HTML\n", "css_file = '../styles/StyleCursoPython.css'\n", "HTML(open(css_file, \"r\").read())" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "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.6.5" } }, "nbformat": 4, "nbformat_minor": 1 }