{ "metadata": { "name": "" }, "nbformat": 3, "nbformat_minor": 0, "worksheets": [ { "cells": [ { "cell_type": "heading", "level": 1, "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Parte 2 - Arrays de NumPy" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## \u00bfQu\u00e9 es NumPy?\n", "\n", "* Una biblioteca para Python: `ndarray` + `ufunc`\n", "* Los arrays multidimensionales (`ndarray`) nos permiten almacenar datos de manera estructurada\n", "* Las funciones universales (`ufunc`) nos permiten operar con esos datos de manera eficiente" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Python est\u00e1 organizado en m\u00f3dulos, que son archivos con extensi\u00f3n `.py` que contienen funciones, variables y otros objetos, y paquetes, que son conjuntos de m\u00f3dulos. Cuando queremos utilizar objetos que est\u00e1n definidos en un m\u00f3dulo tenemos que *importarlo*, y una vez que lo hemos hecho podemos usar el operador `.` para ir descendiendo en la jerarqu\u00eda de paquetes y acceder al objeto que necesitamos. Por ejemplo, de esta manera importamos NumPy:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "import numpy" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 1 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Y de esta manera accedemos a la funci\u00f3n `norm`, que calcula la norma (o m\u00f3dulo) de un array:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "numpy.linalg.norm" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 2, "text": [ "" ] } ], "prompt_number": 2 }, { "cell_type": "markdown", "metadata": {}, "source": [ "La funci\u00f3n `norm` est\u00e1 dentro del paquete `linalg`, que a su vez est\u00e1 dentro del paquete NumPy." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "La convenci\u00f3n para importar NumPy siempre es esta:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "import numpy as np" ], "language": "python", "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "prompt_number": 3 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Lo que hacemos es crear un *alias* al paquete NumPy de nombre `np`. Es simplemente una forma de abreviar el c\u00f3digo. Esta forma de separar las funciones en paquetes (que se llaman **espacios de nombres** o *namespaces*) conduce a una mayor legibilidad del c\u00f3digo y a la supresi\u00f3n de ambig\u00fcedades." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Para encontrar ayuda sobre cierto tema podemos usar la funci\u00f3n `lookfor`:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "np.lookfor(\"solve\")" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "Search results for 'solve'\n", "--------------------------\n", "numpy.linalg.solve\n", " Solve a linear matrix equation, or system of linear scalar equations.\n", "numpy.linalg.lstsq\n", " Return the least-squares solution to a linear matrix equation.\n", "numpy.linalg.tensorsolve\n", " Solve the tensor equation ``a x = b`` for x.\n", "numpy.linalg._umath_linalg.solve\n", " solve the system a x = b, on the last two dimensions, broadcast to the rest.\n", "numpy.linalg._umath_linalg.solve1\n", " solve the system a x = b, for b being a vector, broadcast in the outer dimensions.\n", "numpy.distutils.misc_util.njoin\n", " Join two or more pathname components +\n", "numpy.distutils.misc_util.minrelpath\n", " Resolve `..` and '.' from path.\n", "numpy.distutils.system_info.UmfpackNotFoundError\n", " UMFPACK sparse solver (http://www.cise.ufl.edu/research/sparse/umfpack/)\n", "numpy.linalg.pinv\n", " Compute the (Moore-Penrose) pseudo-inverse of a matrix.\n", "numpy.linalg.cholesky\n", " Cholesky decomposition.\n", "numpy.linalg.tensorinv\n", " Compute the 'inverse' of an N-dimensional array.\n", "numpy.linalg.LinAlgError\n", " Generic Python-exception-derived object raised by linalg functions.\n", "numpy.polynomial.hermite.hermfit\n", " Least squares fit of Hermite series to data.\n", "numpy.polynomial.laguerre.lagfit\n", " Least squares fit of Laguerre series to data.\n", "numpy.polynomial.legendre.legfit\n", " Least squares fit of Legendre series to data.\n", "numpy.polynomial.chebyshev.chebfit\n", " Least squares fit of Chebyshev series to data.\n", "numpy.polynomial.hermite_e.hermefit\n", " Least squares fit of Hermite series to data.\n", "numpy.polynomial.polynomial.polyfit\n", " Least-squares fit of a polynomial to data." ] } ], "prompt_number": 4 }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Constantes y funciones matem\u00e1ticas" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Adem\u00e1s de arrays, NumPy contiene tambi\u00e9n constantes y funciones matem\u00e1ticas de uso cotidiano." ] }, { "cell_type": "code", "collapsed": false, "input": [ "np.e" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 5, "text": [ "2.718281828459045" ] } ], "prompt_number": 5 }, { "cell_type": "code", "collapsed": false, "input": [ "np.pi" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 6, "text": [ "3.141592653589793" ] } ], "prompt_number": 6 }, { "cell_type": "code", "collapsed": false, "input": [ "np.log(2)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 7, "text": [ "0.69314718055994529" ] } ], "prompt_number": 7 }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## \u00bfQu\u00e9 es exactamente un array?\n", "\n", "Un array de NumPy es una colecci\u00f3n de `N` elementos, igual que una secuencia de Python (por ejemplo, una lista). Tiene las mismas propiedades que una secuencia y alguna m\u00e1s. Para crear un array, la forma m\u00e1s directa es pasarle una secuencia a la funci\u00f3n `np.array`." ] }, { "cell_type": "code", "collapsed": false, "input": [ "np.array([1, 2, 3])" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 8, "text": [ "array([1, 2, 3])" ] } ], "prompt_number": 8 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Los arrays de NumPy son *homog\u00e9neos*, es decir, todos sus elementos son del mismo tipo. Si le pasamos a `np.array` una secuencia con objetos de tipos diferentes, promocionar\u00e1 todos al tipo con m\u00e1s informaci\u00f3n. Para acceder al tipo del array, podemos usar el atributo `dtype`." ] }, { "cell_type": "code", "collapsed": false, "input": [ "a = np.array([1, 2, 3.0])\n", "print(a.dtype)" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "float64\n" ] } ], "prompt_number": 9 }, { "cell_type": "code", "collapsed": false, "input": [ "np.array([1, 2, \"3\"])" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 10, "text": [ "array(['1', '2', '3'], \n", " dtype='**Nota**: Si NumPy no entiende el tipo de datos o construimos un array con argumentos incorrectos devolver\u00e1 un array con `dtype` `object`. Estos arrays rara vez son \u00fatiles y su aparici\u00f3n suele ser signo de que algo falla en nuestro programa." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "notes" } }, "source": [ "NumPy intentar\u00e1 autom\u00e1ticamente construir un array con el tipo adecuado teniendo en cuenta los datos de entrada, aunque nosotros podemos forzarlo." ] }, { "cell_type": "code", "collapsed": false, "input": [ "np.array([1, 2, 3], dtype=float)" ], "language": "python", "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 11, "text": [ "array([ 1., 2., 3.])" ] } ], "prompt_number": 11 }, { "cell_type": "code", "collapsed": false, "input": [ "np.array([1, 2, 3], dtype=complex)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 12, "text": [ "array([ 1.+0.j, 2.+0.j, 3.+0.j])" ] } ], "prompt_number": 12 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Tambi\u00e9n podemos convertir un array de un tipo a otro utilizando el m\u00e9todo `.astype`." ] }, { "cell_type": "code", "collapsed": false, "input": [ "a" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 13, "text": [ "array([ 1., 2., 3.])" ] } ], "prompt_number": 13 }, { "cell_type": "code", "collapsed": false, "input": [ "a.astype(int)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 14, "text": [ "array([1, 2, 3])" ] } ], "prompt_number": 14 }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Motivo: eficiencia\n", "\n", "* Los bucles son costosos\n", "* Eliminar bucles: **vectorizar** operaciones\n", "* Los bucles se ejecutan en Python, las operaciones vectorizadas en C\n", "* Las operaciones entre arrays de NumPy se realizan **elemento a elemento**\n", "\n", "Ejemplo:\n", "\n", "$$ a_{ij} = b_{ij} + c_{ij} $$" ] }, { "cell_type": "code", "collapsed": false, "input": [ "N, M = 100, 100\n", "a = np.empty(10000).reshape(N, M)\n", "b = np.random.rand(10000).reshape(N, M)\n", "c = np.random.rand(10000).reshape(N, M)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 15 }, { "cell_type": "code", "collapsed": false, "input": [ "%%timeit\n", "for i in range(N):\n", " for j in range(M):\n", " a[i, j] = b[i, j] + c[i, j]" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "100 loops, best of 3: 8.75 ms per loop\n" ] } ], "prompt_number": 16 }, { "cell_type": "code", "collapsed": false, "input": [ "%%timeit\n", "a = b + c" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "100000 loops, best of 3: 8.34 \u00b5s per loop\n" ] } ], "prompt_number": 17 }, { "cell_type": "markdown", "metadata": {}, "source": [ "\u00a11000 veces m\u00e1s r\u00e1pido! Se hace fundamental **vectorizar** las operaciones y aprovechar al m\u00e1ximo la velocidad de NumPy." ] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Indexaci\u00f3n de arrays" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Una de las herramientas m\u00e1s importantes a la hora de trabajar con arrays es el indexado. Consiste en seleccionar elementos aislados o secciones de un array. Nosotros vamos a ver la indexaci\u00f3n b\u00e1sica, pero existen t\u00e9cnicas de indexaci\u00f3n avanzada que convierten los arrays en herramientas potent\u00edsimas." ] }, { "cell_type": "code", "collapsed": false, "input": [ "a = np.array([\n", " [1, 2, 3],\n", " [4, 5, 6]\n", "])\n", "a" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 18, "text": [ "array([[1, 2, 3],\n", " [4, 5, 6]])" ] } ], "prompt_number": 18 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Los \u00edndices se indican entre corchetes justo despu\u00e9s del array. Recuerda que en Python la indexaci\u00f3n empieza en 0. Si recuperamos el primer elemento de un array de dos dimensiones, obtenemos la primera fila." ] }, { "cell_type": "code", "collapsed": false, "input": [ "a[0]" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 19, "text": [ "array([1, 2, 3])" ] } ], "prompt_number": 19 }, { "cell_type": "markdown", "metadata": {}, "source": [ "En vez de usar `a[0][0]` para recuperar el primer elemento de la primera fila, podemos abreviar a\u00fan m\u00e1s la sintaxis:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "a[0, 0]" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 20, "text": [ "1" ] } ], "prompt_number": 20 }, { "cell_type": "markdown", "metadata": {}, "source": [ "No solo podemos recuperar un elemento aislado, sino tambi\u00e9n porciones del array, utilizando la sintaxis `[::]`." ] }, { "cell_type": "code", "collapsed": false, "input": [ "a[0, 1:3]" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 21, "text": [ "array([2, 3])" ] } ], "prompt_number": 21 }, { "cell_type": "code", "collapsed": false, "input": [ "a[0, ::2]" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 22, "text": [ "array([1, 3])" ] } ], "prompt_number": 22 }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Creaci\u00f3n de arrays\n", "\n", "Muchos m\u00e9todos y muy variados\n", "\n", "* A partir de datos existentes: `array`, `copy`\n", "* Unos y ceros: `empty`, `eye`, `ones`, `zeros`, `*_like`\n", "* Rangos: `arange`, `linspace`, `logspace`, `meshgrid`\n", "* Aleatorios: `rand`, `randn`" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Unos y ceros\n", "\n", "* `empty(shape)` crea un array con \u00abbasura\u00bb, equivalente a no inicializarlo, ligeramente m\u00e1s r\u00e1pido que `zeros` o `ones`\n", "* `eye(N, M=None, k=0)` crea un array con unos en una diagonal y ceros en el resto\n", "* `identity(n)` devuelve la matriz identidad\n", "* Las funciones `*_like(a)` construyen arrays con el mismo tama\u00f1o que uno dado" ] }, { "cell_type": "code", "collapsed": false, "input": [ "np.identity(5).astype(int)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 23, "text": [ "array([[1, 0, 0, 0, 0],\n", " [0, 1, 0, 0, 0],\n", " [0, 0, 1, 0, 0],\n", " [0, 0, 0, 1, 0],\n", " [0, 0, 0, 0, 1]])" ] } ], "prompt_number": 23 }, { "cell_type": "code", "collapsed": false, "input": [ "_.shape" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 24, "text": [ "(5, 5)" ] } ], "prompt_number": 24 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Si la funci\u00f3n recibe como argumento `shape`, debemos pasarle el n\u00famero de filas y columnas como una tupla (es decir, encerrado entre par\u00e9ntesis)." ] }, { "cell_type": "code", "collapsed": false, "input": [ "np.zeros((3, 4))" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 25, "text": [ "array([[ 0., 0., 0., 0.],\n", " [ 0., 0., 0., 0.],\n", " [ 0., 0., 0., 0.]])" ] } ], "prompt_number": 25 }, { "cell_type": "markdown", "metadata": {}, "source": [ "
**Nota**: Un error muy t\u00edpico es tratar de construir un array llamando a la funci\u00f3n con dos argumentos, como se ejemplifica en la celda siguiente. Esto produce un error, porque NumPy espera un solo argumento: una tupla con el n\u00famero de filas y el n\u00famero de columnas. Es conveniente asegurarse de cu\u00e1l es el convenio en cada caso porque no siempre hay consistencia interna.
" ] }, { "cell_type": "code", "collapsed": false, "input": [ "np.zeros(3, 4)" ], "language": "python", "metadata": {}, "outputs": [ { "ename": "TypeError", "evalue": "data type not understood", "output_type": "pyerr", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)", "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mzeros\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[0m\n\u001b[0m", "\u001b[1;31mTypeError\u001b[0m: data type not understood" ] } ], "prompt_number": 26 }, { "cell_type": "code", "collapsed": false, "input": [ "np.ones((3, 4))" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 27, "text": [ "array([[ 1., 1., 1., 1.],\n", " [ 1., 1., 1., 1.],\n", " [ 1., 1., 1., 1.]])" ] } ], "prompt_number": 27 }, { "cell_type": "code", "collapsed": false, "input": [ "i3 = np.identity(3)\n", "i3" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 28, "text": [ "array([[ 1., 0., 0.],\n", " [ 0., 1., 0.],\n", " [ 0., 0., 1.]])" ] } ], "prompt_number": 28 }, { "cell_type": "code", "collapsed": false, "input": [ "i3.shape" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 29, "text": [ "(3, 3)" ] } ], "prompt_number": 29 }, { "cell_type": "code", "collapsed": false, "input": [ "np.ones(i3.shape)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 30, "text": [ "array([[ 1., 1., 1.],\n", " [ 1., 1., 1.],\n", " [ 1., 1., 1.]])" ] } ], "prompt_number": 30 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Si en lugar de pasar directamente la forma del array ya sabemos que queremos crear un array con la misma forma que otro, podemos usar las funciones `*_like`, que reciben un array en vez de una tupla." ] }, { "cell_type": "code", "collapsed": false, "input": [ "np.ones_like(i3)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 31, "text": [ "array([[ 1., 1., 1.],\n", " [ 1., 1., 1.],\n", " [ 1., 1., 1.]])" ] } ], "prompt_number": 31 }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Rangos\n", "\n", "* `linspace(start, stop, num=50)` devuelve n\u00fameros equiespaciados dentro de un intervalo\n", "* `logspace(start, stop, num=50, base=10.0)` devuelve n\u00fameros equiespaciados seg\u00fan una escala logar\u00edtmica\n", "* `meshgrid(x1, x2, ...)` devuelve matrices de n-coordenadas" ] }, { "cell_type": "code", "collapsed": false, "input": [ "np.linspace(0, 1, num=10)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 32, "text": [ "array([ 0. , 0.11111111, 0.22222222, 0.33333333, 0.44444444,\n", " 0.55555556, 0.66666667, 0.77777778, 0.88888889, 1. ])" ] } ], "prompt_number": 32 }, { "cell_type": "code", "collapsed": false, "input": [ "np.logspace(0, 3)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 33, "text": [ "array([ 1. , 1.1513954 , 1.32571137, 1.52641797,\n", " 1.75751062, 2.02358965, 2.32995181, 2.6826958 ,\n", " 3.0888436 , 3.55648031, 4.09491506, 4.71486636,\n", " 5.42867544, 6.25055193, 7.19685673, 8.28642773,\n", " 9.54095476, 10.98541142, 12.64855217, 14.56348478,\n", " 16.76832937, 19.30697729, 22.22996483, 25.59547923,\n", " 29.47051703, 33.93221772, 39.06939937, 44.98432669,\n", " 51.79474679, 59.63623317, 68.6648845 , 79.06043211,\n", " 91.0298178 , 104.81131342, 120.67926406, 138.94954944,\n", " 159.98587196, 184.20699693, 212.09508879, 244.20530945,\n", " 281.1768698 , 323.74575428, 372.75937203, 429.19342601,\n", " 494.17133613, 568.9866029 , 655.12855686, 754.31200634,\n", " 868.51137375, 1000. ])" ] } ], "prompt_number": 33 }, { "cell_type": "markdown", "metadata": {}, "source": [ "La funci\u00f3n `np.meshgrid` se utiliza mucho a la hora de representar funciones en dos dimensiones, y crea dos arrays: uno var\u00eda por filas y otro por columnas. Combin\u00e1ndolos, podemos evaluar la funci\u00f3n en un cuadrado." ] }, { "cell_type": "code", "collapsed": false, "input": [ "x = np.linspace(0, 1, num=5)\n", "y = np.linspace(0, 1, num=5)\n", "\n", "xx, yy = np.meshgrid(x, y)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 37 }, { "cell_type": "code", "collapsed": false, "input": [ "xx, yy" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 38, "text": [ "(array([[ 0. , 0.25, 0.5 , 0.75, 1. ],\n", " [ 0. , 0.25, 0.5 , 0.75, 1. ],\n", " [ 0. , 0.25, 0.5 , 0.75, 1. ],\n", " [ 0. , 0.25, 0.5 , 0.75, 1. ],\n", " [ 0. , 0.25, 0.5 , 0.75, 1. ]]),\n", " array([[ 0. , 0. , 0. , 0. , 0. ],\n", " [ 0.25, 0.25, 0.25, 0.25, 0.25],\n", " [ 0.5 , 0.5 , 0.5 , 0.5 , 0.5 ],\n", " [ 0.75, 0.75, 0.75, 0.75, 0.75],\n", " [ 1. , 1. , 1. , 1. , 1. ]]))" ] } ], "prompt_number": 38 }, { "cell_type": "code", "collapsed": false, "input": [ "xx + 1j * yy" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 39, "text": [ "array([[ 0.00+0.j , 0.25+0.j , 0.50+0.j , 0.75+0.j , 1.00+0.j ],\n", " [ 0.00+0.25j, 0.25+0.25j, 0.50+0.25j, 0.75+0.25j, 1.00+0.25j],\n", " [ 0.00+0.5j , 0.25+0.5j , 0.50+0.5j , 0.75+0.5j , 1.00+0.5j ],\n", " [ 0.00+0.75j, 0.25+0.75j, 0.50+0.75j, 0.75+0.75j, 1.00+0.75j],\n", " [ 0.00+1.j , 0.25+1.j , 0.50+1.j , 0.75+1.j , 1.00+1.j ]])" ] } ], "prompt_number": 39 }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Operaciones con arrays\n", "\n", "Las **funciones universales** (`ufunc`) operan sobre arrays de NumPy elemento a elemento y siguiendo las reglas de _broadcasting_.\n", "\n", "* Funciones matem\u00e1ticas: `sin`, `cos`, `sqrt`, `exp`, ...\n", "* Operaciones l\u00f3gicas: `<`, `~`, ...\n", "* Funciones l\u00f3gicas: `all`, `any`, `isnan`, `allclose`, ..." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "
**Nota**: Las funciones matem\u00e1ticas siempre devuelven el mismo tipo de datos de entrada
" ] }, { "cell_type": "code", "collapsed": false, "input": [ "a = np.arange(2 * 3).reshape(2, 3)\n", "a" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 40, "text": [ "array([[0, 1, 2],\n", " [3, 4, 5]])" ] } ], "prompt_number": 40 }, { "cell_type": "code", "collapsed": false, "input": [ "np.sqrt(a)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 41, "text": [ "array([[ 0. , 1. , 1.41421356],\n", " [ 1.73205081, 2. , 2.23606798]])" ] } ], "prompt_number": 41 }, { "cell_type": "code", "collapsed": false, "input": [ "np.sqrt(np.arange(-3, 3))" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stderr", "text": [ "-c:1: RuntimeWarning: invalid value encountered in sqrt\n" ] }, { "metadata": {}, "output_type": "pyout", "prompt_number": 42, "text": [ "array([ nan, nan, nan, 0. , 1. ,\n", " 1.41421356])" ] } ], "prompt_number": 42 }, { "cell_type": "code", "collapsed": false, "input": [ "np.arange(-3, 3).astype(complex)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 43, "text": [ "array([-3.+0.j, -2.+0.j, -1.+0.j, 0.+0.j, 1.+0.j, 2.+0.j])" ] } ], "prompt_number": 43 }, { "cell_type": "code", "collapsed": false, "input": [ "np.sqrt(_)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 44, "text": [ "array([ 0.00000000+1.73205081j, 0.00000000+1.41421356j,\n", " 0.00000000+1.j , 0.00000000+0.j ,\n", " 1.00000000+0.j , 1.41421356+0.j ])" ] } ], "prompt_number": 44 }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Funciones de comparaci\u00f3n\n", "\n", "Las comparaciones devuelven un array de booleanos:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "a = np.arange(6)\n", "b = np.ones(6).astype(int)\n", "a, b" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 45, "text": [ "(array([0, 1, 2, 3, 4, 5]), array([1, 1, 1, 1, 1, 1]))" ] } ], "prompt_number": 45 }, { "cell_type": "code", "collapsed": false, "input": [ "a < b" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 46, "text": [ "array([ True, False, False, False, False, False], dtype=bool)" ] } ], "prompt_number": 46 }, { "cell_type": "code", "collapsed": false, "input": [ "np.any(a < b)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 47, "text": [ "True" ] } ], "prompt_number": 47 }, { "cell_type": "code", "collapsed": false, "input": [ "np.all(a < b)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 48, "text": [ "False" ] } ], "prompt_number": 48 }, { "cell_type": "code", "collapsed": false, "input": [ "a = np.arange(6).astype(float)\n", "b = np.ones(6)\n", "a, b" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 49, "text": [ "(array([ 0., 1., 2., 3., 4., 5.]), array([ 1., 1., 1., 1., 1., 1.]))" ] } ], "prompt_number": 49 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Las funciones `isclose` y `allclose` realizan comparaciones entre arrays especificando una tolerancia:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "np.isclose(a, b, rtol=1e-6)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 50, "text": [ "array([False, True, False, False, False, False], dtype=bool)" ] } ], "prompt_number": 50 }, { "cell_type": "code", "collapsed": false, "input": [ "np.allclose(a, b, rtol=1e-6)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 51, "text": [ "False" ] } ], "prompt_number": 51 }, { "cell_type": "markdown", "metadata": {}, "source": [ "
**\u00a1Importante!** Ni en Python ni en ning\u00fan otro lenguaje debemos hacer comparaciones exactas entre n\u00fameros de punto flotante. Las operaciones matem\u00e1ticas con estos n\u00fameros producen casi siempre resultados poco intuitivos y hay que tener cuidado con ellas. Para una introducci\u00f3n a estas peculiaridades existe la web http://puntoflotante.org/.
" ] }, { "cell_type": "code", "collapsed": false, "input": [ "0.1 + 0.2 + 0.3" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 52, "text": [ "0.6000000000000001" ] } ], "prompt_number": 52 }, { "cell_type": "code", "collapsed": false, "input": [ "0.3 + 0.2 + 0.1" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 53, "text": [ "0.6" ] } ], "prompt_number": 53 }, { "cell_type": "code", "collapsed": false, "input": [ "0.1 + 0.2 + 0.3 == 0.3 + 0.2 + 0.1" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 54, "text": [ "False" ] } ], "prompt_number": 54 }, { "cell_type": "heading", "level": 1, "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Ejercicios" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Ejercicio 1.\n", "\n", "1. Crear un array `z1` 3x4 lleno de ceros de tipo entero.\n", "2. Crear un array `z2` 3x4 lleno de ceros salvo la primera fila que ser\u00e1n todo unos.\n", "3. Crear un array `z3` 3x4 lleno de ceros salvo la \u00faltima fila que ser\u00e1 el rango entre 5 y 8." ] }, { "cell_type": "code", "collapsed": false, "input": [ "a = np.zeros((3, 4))\n", "a" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 55, "text": [ "array([[ 0., 0., 0., 0.],\n", " [ 0., 0., 0., 0.],\n", " [ 0., 0., 0., 0.]])" ] } ], "prompt_number": 55 }, { "cell_type": "code", "collapsed": false, "input": [ "a[0, :] = 1\n", "a" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 56, "text": [ "array([[ 1., 1., 1., 1.],\n", " [ 0., 0., 0., 0.],\n", " [ 0., 0., 0., 0.]])" ] } ], "prompt_number": 56 }, { "cell_type": "code", "collapsed": false, "input": [ "b = np.zeros((3, 4))\n", "b[-1] = np.arange(5, 9)\n", "b" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 57, "text": [ "array([[ 0., 0., 0., 0.],\n", " [ 0., 0., 0., 0.],\n", " [ 5., 6., 7., 8.]])" ] } ], "prompt_number": 57 }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Ejercicio 2.\n", "\n", "1. Crea un vector de 10 elementos, siendo los impares unos y los pares doses.\n", "2. Crea un \u00abtablero de ajedrez\u00bb, con unos en las casillas negras y ceros en las blancas." ] }, { "cell_type": "code", "collapsed": false, "input": [ "v = np.ones(10)\n", "v" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 58, "text": [ "array([ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])" ] } ], "prompt_number": 58 }, { "cell_type": "code", "collapsed": false, "input": [ "v[::2] = 2\n", "v" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 59, "text": [ "array([ 2., 1., 2., 1., 2., 1., 2., 1., 2., 1.])" ] } ], "prompt_number": 59 }, { "cell_type": "code", "collapsed": false, "input": [ "tablero = np.zeros((8, 8))\n", "tablero" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 60, "text": [ "array([[ 0., 0., 0., 0., 0., 0., 0., 0.],\n", " [ 0., 0., 0., 0., 0., 0., 0., 0.],\n", " [ 0., 0., 0., 0., 0., 0., 0., 0.],\n", " [ 0., 0., 0., 0., 0., 0., 0., 0.],\n", " [ 0., 0., 0., 0., 0., 0., 0., 0.],\n", " [ 0., 0., 0., 0., 0., 0., 0., 0.],\n", " [ 0., 0., 0., 0., 0., 0., 0., 0.],\n", " [ 0., 0., 0., 0., 0., 0., 0., 0.]])" ] } ], "prompt_number": 60 }, { "cell_type": "code", "collapsed": false, "input": [ "tablero[1::2, ::2] = 1\n", "tablero[::2, 1::2] = 1\n", "tablero" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 61, "text": [ "array([[ 0., 1., 0., 1., 0., 1., 0., 1.],\n", " [ 1., 0., 1., 0., 1., 0., 1., 0.],\n", " [ 0., 1., 0., 1., 0., 1., 0., 1.],\n", " [ 1., 0., 1., 0., 1., 0., 1., 0.],\n", " [ 0., 1., 0., 1., 0., 1., 0., 1.],\n", " [ 1., 0., 1., 0., 1., 0., 1., 0.],\n", " [ 0., 1., 0., 1., 0., 1., 0., 1.],\n", " [ 1., 0., 1., 0., 1., 0., 1., 0.]])" ] } ], "prompt_number": 61 }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Ejercicio 3.\n", "\n", "1. Crea una matriz aleatoria 5x5 y halla los valores m\u00ednimo y m\u00e1ximo.\n", "2. Normaliza esa matriz entre 0 y 1." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Bibliograf\u00eda\n", "\n", "* Documentaci\u00f3n de NumPy http://docs.scipy.org/doc/numpy\n", "* Travis Oliphant, \"Guide to NumPy\" http://csc.ucdavis.edu/~chaos/courses/nlp/Software/NumPyBook.pdf\n", "* SciPy Lecture Notes http://scipy-lectures.github.io\n", "* Nicolas Rougier, \"100 NumPy exercises\" http://www.loria.fr/~rougier/teaching/numpy.100/index.html" ] } ], "metadata": {} } ] }