From 914f700b2a22c2bb16ac41de1db4ff6254828001 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Gait=C3=A1n?= Date: Tue, 22 Sep 2015 01:54:30 -0300 Subject: [PATCH] clase 4 --- Clase 3.ipynb | 2492 ++++++++++++++++++------------------- Clase 4.ipynb | 3104 +++++++++++++++++++++++++++------------------- img/image001.gif | Bin 0 -> 2987 bytes img/image002.gif | Bin 0 -> 6641 bytes img/image003.gif | Bin 0 -> 4681 bytes img/image004.gif | Bin 0 -> 7287 bytes 6 files changed, 3020 insertions(+), 2576 deletions(-) create mode 100644 img/image001.gif create mode 100644 img/image002.gif create mode 100644 img/image003.gif create mode 100644 img/image004.gif diff --git a/Clase 3.ipynb b/Clase 3.ipynb index aa1a6b2..947ae09 100644 --- a/Clase 3.ipynb +++ b/Clase 3.ipynb @@ -58,19 +58,11 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": { "collapsed": false }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Overwriting cuadratica.py\n" - ] - } - ], + "outputs": [], "source": [ "%%writefile cuadratica.py \n", "\n", @@ -85,26 +77,6 @@ " " ] }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "%%writefile?" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [] - }, { "cell_type": "markdown", "metadata": {}, @@ -114,7 +86,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": { "collapsed": false }, @@ -132,13 +104,13 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ - "cuadratica.raices??" + "cuadratica.raices?" ] }, { @@ -174,29 +146,7 @@ }, { "cell_type": "code", - "execution_count": 10, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "data": { - "text/plain": [ - "(0.0, 0.0)" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "cuad.raices(2)" - ] - }, - { - "cell_type": "code", - "execution_count": 9, + "execution_count": null, "metadata": { "collapsed": false }, @@ -216,7 +166,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "metadata": { "collapsed": false }, @@ -228,24 +178,13 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": null, "metadata": { - "collapsed": false + "collapsed": true }, - "outputs": [ - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 17, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ - "raices is cuadratica.raices" + "raices?" ] }, { @@ -265,491 +204,879 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "#### Ejercicios\n", + "### Ejercicios\n", "\n", "1. Cree un módulo `circunferencia.py` que defina una constante `PI` y una función `area(r)` que calcula el área para una circunferencia de radio `r`. \n", "\n", - "2. Desde una celda de la sesión interactiva, importe todo el módulo como un alias `circle` y verifique `circle.PI` y `circle.area()`. Luego importe utilizando la forma `from circunferencia import ...` que importe también la función y la constante\n", + "2. Desde una celda de la sesión intereactiva, importe todo el módulo como un alias `circle` y verifique `circle.PI` y `circle.area()`. Luego importe utilizando la forma `from circunferencia import ...` que importe también la función y la constante\n", "\n", "3. verifique que circle.area y area son el mismo objeto" ] }, { - "cell_type": "code", - "execution_count": 18, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Writing circunferencia.py\n" - ] - } - ], + "cell_type": "markdown", + "metadata": {}, "source": [ - "%%writefile circunferencia.py\n", + "#### Paquetes: módulos de módulos\n", "\n", - "__all__ = ['area', 'PI']\n", + "Cuando tenemos muchos módulos que están relacionados es bueno armar un **paquete**. Un paquete de modulos es un simple directorio con un módulo especial llamado `__init__.py` (que puede estar vacio) y tantos modulos y subpaquetes como queramos. \n", "\n", "\n", + "Los paquetes se usan igual que un módulo. Por ejemplo, supongamos que tenemos una estructura\n", "\n", + " paquete/\n", + " __init__.py\n", + " modulo.py\n", "\n", - "from funciones_especiales import blah\n", - "from math import pi\n", - "PI = pi\n", + "Puedo importar la `funcion_loca` definida en `modulo.py` así \n", "\n", - "def area(r):\n", - " return PI*r**2" + " from paquete.modulo import funcion_loca \n" ] }, { "cell_type": "code", - "execution_count": 25, + "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ - "\n", - "class A:\n", - " PI = 32\n", - " \n", - " def __init__(self, pi=3.14):\n", - " self.pi = pi\n", - " \n" + "%mkdir paquete # creamos un directorio \"paquete\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": { - "collapsed": true + "collapsed": false }, "outputs": [], - "source": [] + "source": [ + "%%writefile paquete/__init__.py # el archivo __init__.py vacio\n", + " " + ] }, { "cell_type": "code", - "execution_count": 26, + "execution_count": null, "metadata": { - "collapsed": true + "collapsed": false }, "outputs": [], "source": [ - "mi_a = A()\n" + "%%writefile paquete/modulo.py\n", + "\n", + "def funcion_loca(w=300,h=200):\n", + " _ = (\n", + " 255,\n", + " lambda\n", + " V ,B,c\n", + " :c and Y(V*V+B,B, c\n", + " -1)if(abs(V)<6)else\n", + " ( 2+c-4*abs(V)**-.4)/i\n", + " ) ;v, x=w,h; C = range(-1,v*x \n", + " +1);import struct; P = struct.pack;M, \\\n", + " j =b'?@[\\]^_`{|}~\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Escribir programas de línea de comando\n", + "\n", + "\n", + "Ya vimos que es muy simple ejecutar un módulo de python como un **script**. Simplemente hay que pasar como parámetro al ejecutable python el módulo en cuestión \n", + "\n", + " python archivo.py\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Overwriting ejemplo_script.py\n" + ] + } + ], + "source": [ + "%%writefile ejemplo_script.py\n", "\n", - "with open('pesos.csv', 'w') as pesos_csv:\n", - " writer = csv.writer(pesos_csv)\n", - " writer.writerows(datos)" + "saludo = \"Hola Mundo\"\n", + "\n", + "print(saludo)" ] }, { "cell_type": "code", - "execution_count": 51, + "execution_count": 2, "metadata": { "collapsed": false }, @@ -758,92 +1085,80 @@ "name": "stdout", "output_type": "stream", "text": [ - "Nombre,Peso\r", - "\r\n", - "Juan,92\r", - "\r\n", - "\"La \"\"Mole\"\" Moli\",121\r", - "\r\n", - "Martín,5 kilos de más\r", - "\r\n" + "Hola Mundo\r\n" ] } ], "source": [ - "%cat pesos.csv" + "!python ejemplo_script.py" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Ejercicios:\n", - "\n", - "1. Dado un archivo CSV `circuitos.csv` (en la siguiente celda), leerlo utilizando `csv.DictReader` en vez de `csv.reader` y devolver todas las filas en una lista. Notar que el delimitador es `;` en vez de coma. \n", - "\n", - "2. Genere un archivo csv donde la primera columna es la serie de enteros 1 a 10 inclusive, la segunda columna el logaritmo natural para el numero correspondiente de la primera columna, y una tercera que el logaritmo en base 10. \n", - "\n", - " [(i, math.log(i), math.log10(i)) for i in range(1, 11)]\n" + "El tema es que si importamos ese módulo desde la sesión interactiva o desde otro módulo, tambien se ejecutará todo el código que defina" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": { "collapsed": false }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Hola Mundo\n", + "Hola Mundo\n" + ] + } + ], "source": [ - "%%writefile circuitos.csv\n", - "long;lat;CODIGO DE ESTABLECIMIENTO;NOMBRE ESTABLECIMIENTO;DOMICILIO;CIRCUITO;DESDE MESA;HASTA MESA;TOTAL MESAS;Dirección Normalizada\n", - "-58.372807778869245;-34.622409314430783;4369;ESC N°3 BERNARDINO RIVADAVIA;BOLIVAR 1235;1;19;28;10;BOLIVAR 1235\n", - "-58.384400577996836;-34.593569986274616;4593;COL. NAC.Nº2 D F SARMIENTO;LIBERTAD 1257;6;115;136;22;LIBERTAD 1257\n", - "-58.373914555842283;-34.602665313935738;4409;ESC N°13 GRAL SAN MARTIN;SAN MARTIN 458;9;192;206;15;SAN MARTIN 458\n", - "-58.383791453750931;-34.601733848426591;5330;ESC N°7 PTE ROCA;LIBERTAD 581;10;225;234;10;LIBERTAD 581\n", - "-58.388829352224974;-34.605387432219594;9026;UMSA UNIV DE MUSEO SOCIAL ARG;SARMIENTO 1565;10;252;259;8;SARMIENTO 1565\n", - "-58.373317952774258;-34.611859568515861;5118;ESC POLITECNICA Nº5 M BELGRANO;BOLIVAR 346;14;367;371;5;BOLIVAR 346\n", - "-58.373438804697628;-34.610990941996334;8716;COLEGIO NACIONAL BUENOS AIRES;BOLIVAR 263;14;372;381;10;BOLIVAR 263" + "from ejemplo_script import saludo\n", + "print(saludo)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Números aleatorios\n", - "\n", - "Todas las funciones relacionadas a la aleatoriedad están en el módulo `random`. \n", + "A veces queremos que **se ejecute algo sólo cuando lo invocamos como script** y no cuando lo importamos. \n", "\n", - "Ver [documentación](https://docs.python.org/3/library/random.html)" + "Para eso podemos valernos de que Python asigna el nombre `__main__` al módulo principal con que fue llamado, en la variable global `__name__`" ] }, { "cell_type": "code", - "execution_count": 53, + "execution_count": 4, "metadata": { "collapsed": false }, "outputs": [ { - "data": { - "text/plain": [ - "0.5155237329761995" - ] - }, - "execution_count": 53, - "metadata": {}, - "output_type": "execute_result" + "name": "stdout", + "output_type": "stream", + "text": [ + "Writing ejemplo_script2.py\n" + ] } ], "source": [ - "import random\n", + "%%writefile ejemplo_script2.py\n", "\n", - "# la función más básica\n", - "random.random() # float aleatorio, 0.0 <= x < 1.0" + "saludo = \"Hola Mundo\"\n", + "\n", + "if __name__ == '__main__':\n", + " # esto se ejecuta solo cuando el modulo se llama como script\n", + " # no cuando se importa desde otro modulo o desde la sesion interactiva\n", + " print(saludo)" ] }, { "cell_type": "code", - "execution_count": 56, + "execution_count": 5, "metadata": { "collapsed": false }, @@ -851,451 +1166,356 @@ { "data": { "text/plain": [ - "90" + "'Hola'" ] }, - "execution_count": 56, + "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "random.randrange(100, 10, -5) # análogo a range() devuelve un numero aleatorio de la serie" + "from ejemplo_script2 import saludo\n", + "saludo[:4]" ] }, { "cell_type": "code", - "execution_count": 57, + "execution_count": 6, "metadata": { "collapsed": false }, "outputs": [ { - "data": { - "text/plain": [ - "10" - ] - }, - "execution_count": 57, - "metadata": {}, - "output_type": "execute_result" + "name": "stdout", + "output_type": "stream", + "text": [ + "Hola Mundo\r\n" + ] } ], "source": [ - "random.choice([0.3, 10, 'A']) # elige un elemento al azar de una secuencia no vacía" + "!python ejemplo_script2.py" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Si bien un programa de linea de comandos puede solicitar información al usuario interactivamente (por ejemplo, a utilizando la función `input()`), lo más típico es que los argumentos se pasen directamente en la llamada\n", + "\n", + " python mi_programa.py [parametro 2]\n", + " \n", + " \n", + "Python guarda todos los argumentos pasados (incluyendo el nombre del propio módulo) en una lista llamada `argv` del módulo `sys`" ] }, { "cell_type": "code", - "execution_count": 60, + "execution_count": 7, "metadata": { "collapsed": false }, "outputs": [ { - "data": { - "text/plain": [ - "[0.3, 10]" - ] - }, - "execution_count": 60, - "metadata": {}, - "output_type": "execute_result" + "name": "stdout", + "output_type": "stream", + "text": [ + "Writing ejemplo_argv.py\n" + ] } ], "source": [ - "l = [0.3, 10, 'A']\n", - "random.sample(l, k=2) # elige k elementos de la poblacion dada " + "%%writefile ejemplo_argv.py\n", + "\n", + "if __name__ == '__main__':\n", + " import sys\n", + " print(sys.argv)" ] }, { "cell_type": "code", - "execution_count": 62, + "execution_count": 9, "metadata": { "collapsed": false }, "outputs": [ { - "data": { - "text/plain": [ - "[7, 4, 2, 3, 6, 8, 1, 9, 0, 5]" - ] - }, - "execution_count": 62, - "metadata": {}, - "output_type": "execute_result" + "name": "stdout", + "output_type": "stream", + "text": [ + "['ejemplo_argv.py', 'parametro', '10', '--allthenight', '--shampein']\r\n" + ] } ], "source": [ - "l = list(range(10))\n", - "random.shuffle(l) # \"desordena\" una lista (inline)\n", - "l.pop" + "!python ejemplo_argv.py --allthenight --shampein" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "También tiene muchas funciones de probabilidad" + "Para parámetros muy simples podemos buscar valores directamente en esta lista, por ejemplo:\n", + "\n", + " if '--allthenigh' in sys.argv:\n", + " room.append(cristal)\n", + " \n", + "Pero la mayoría de las veces los argumentos posibles son más complejos y se requiere una **librería para procesar los argumentos** dados, convertirlos a un tipo de datos particular, asignar valores defaults a aquellos parametros que no se explicitaron, generar un resumen de la opciones disponibles a modo de ayuda, etc. \n", + "\n", + "Para esto se puede usar el módulo [`argparse`](https://docs.python.org/3/library/argparse.html#module-argparse)\n", + "\n", + "\n" ] }, { "cell_type": "code", - "execution_count": 64, + "execution_count": 16, "metadata": { "collapsed": false }, "outputs": [ { - "data": { - "text/plain": [ - "['BPF',\n", - " 'LOG4',\n", - " 'NV_MAGICCONST',\n", - " 'RECIP_BPF',\n", - " 'Random',\n", - " 'SG_MAGICCONST',\n", - " 'SystemRandom',\n", - " 'TWOPI',\n", - " '_BuiltinMethodType',\n", - " '_MethodType',\n", - " '_Sequence',\n", - " '_Set',\n", - " '__all__',\n", - " '__builtins__',\n", - " '__cached__',\n", - " '__doc__',\n", - " '__file__',\n", - " '__loader__',\n", - " '__name__',\n", - " '__package__',\n", - " '__spec__',\n", - " '_acos',\n", - " '_ceil',\n", - " '_cos',\n", - " '_e',\n", - " '_exp',\n", - " '_inst',\n", - " '_log',\n", - " '_pi',\n", - " '_random',\n", - " '_sha512',\n", - " '_sin',\n", - " '_sqrt',\n", - " '_test',\n", - " '_test_generator',\n", - " '_urandom',\n", - " '_warn',\n", - " 'betavariate',\n", - " 'choice',\n", - " 'expovariate',\n", - " 'gammavariate',\n", - " 'gauss',\n", - " 'getrandbits',\n", - " 'getstate',\n", - " 'lognormvariate',\n", - " 'normalvariate',\n", - " 'paretovariate',\n", - " 'randint',\n", - " 'random',\n", - " 'randrange',\n", - " 'sample',\n", - " 'seed',\n", - " 'setstate',\n", - " 'shuffle',\n", - " 'triangular',\n", - " 'uniform',\n", - " 'vonmisesvariate',\n", - " 'weibullvariate']" - ] - }, - "execution_count": 64, - "metadata": {}, - "output_type": "execute_result" + "name": "stdout", + "output_type": "stream", + "text": [ + "Overwriting prog.py\n" + ] } ], "source": [ - "dir(random)" + "%%writefile prog.py\n", + "\n", + "import argparse\n", + "\n", + "if __name__ == '__main__':\n", + "\n", + " parser = argparse.ArgumentParser(description='Procesa una lista de enteros')\n", + " parser.add_argument('enteros', metavar='N', type=int, nargs='+', # uno o mas argumentos. se acumulan en una lista\n", + " help='an integer for the accumulator')\n", + " parser.add_argument('--sum', dest='operacion', action='store_const', # si se pasa --sum se usará const \n", + " const=sum, default=max, # en vez de default\n", + " help='sum the integers (default: find the max)')\n", + "\n", + " args = parser.parse_args()\n", + " print(args.operacion(args.enteros))" ] }, { "cell_type": "code", - "execution_count": 63, + "execution_count": 18, "metadata": { "collapsed": false }, "outputs": [ { - "data": { - "text/plain": [ - "['betavariate',\n", - " 'expovariate',\n", - " 'gammavariate',\n", - " 'lognormvariate',\n", - " 'normalvariate',\n", - " 'paretovariate',\n", - " 'vonmisesvariate',\n", - " 'weibullvariate']" - ] - }, - "execution_count": 63, - "metadata": {}, - "output_type": "execute_result" + "name": "stdout", + "output_type": "stream", + "text": [ + "usage: prog.py [-h] [--sum] N [N ...]\r\n", + "prog.py: error: the following arguments are required: N\r\n" + ] } ], "source": [ - "[method for method in dir(random) if method.endswith('variate')]" + "!python3 prog.py" ] }, { "cell_type": "code", - "execution_count": 67, + "execution_count": 19, "metadata": { "collapsed": false }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "usage: prog.py [-h] [--sum] N [N ...]\r\n", + "\r\n", + "Procesa una lista de enteros\r\n", + "\r\n", + "positional arguments:\r\n", + " N an integer for the accumulator\r\n", + "\r\n", + "optional arguments:\r\n", + " -h, --help show this help message and exit\r\n", + " --sum sum the integers (default: find the max)\r\n" + ] + } + ], + "source": [ + "!python3 prog.py -h" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "usage: prog.py [-h] [--sum] N [N ...]\r\n", + "prog.py: error: unrecognized arguments: 45\r\n" + ] + } + ], "source": [ - "random.normalvariate??" + "!python3 prog.py 10 2 --sum 45 " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "#### Ejercicio\n", "\n", - "1. Crear un generador de 1000 números aleatorios pertecientes a una curva de probabilidad normal con media 1 y variancia 0.25. \n", + "Tarea: Estudiar la biblioteca estándar de Python ! \n", "\n", - "2. Verificar que la media y la variancia son cercanas a las esperadas (Tip: investigar las funciones del módulo `statistics`)\n" + "--------------\n", + "\n", + "\n", + "\n" ] }, { - "cell_type": "code", - "execution_count": 81, - "metadata": { - "collapsed": false - }, - "outputs": [], + "cell_type": "markdown", + "metadata": {}, "source": [ - "normal = [random.normalvariate(1, 0.25) for n in range(1000)]\n", + "## Matplotlib, un gráfico vale más que mil palabras\n", "\n", - "import statistics as stats" + "Python es un lenguaje muy completo pero aunque es muy grande, su librería estándar no es infinita. Por suerte hay miles y miles de bibliotecas extra para complementar casi cualquier aspecto en el que queramos aplicar Python. En algunos ámbitos, con soluciones muy destacadas. \n", + "\n", + "Para hacer gráficos existe Matplotlib http://matplotlib.org/ . Ya viene instalado con la versión completa de Anaconda. \n" ] }, { "cell_type": "code", - "execution_count": 80, + "execution_count": null, "metadata": { "collapsed": false }, - "outputs": [ - { - "data": { - "text/plain": [ - "0.25535015504245945" - ] - }, - "execution_count": 80, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "stats.stdev(normal)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, + "outputs": [], "source": [ - "## Serialización \n", - "\n", - "A veces queremos **serializar un objeto** cualquiera para poder recuperarlo más adelante. Si sólo nos interesa persistir y recuperar información **a nivel Python** podemos usar le módulo [`pickle`](https://docs.python.org/3.4/library/pickle.html). " + "%matplotlib inline" ] }, { "cell_type": "code", - "execution_count": 84, + "execution_count": null, "metadata": { "collapsed": false }, - "outputs": [ - { - "data": { - "text/plain": [ - "b'\\x80\\x03]q\\x00(X\\x05\\x00\\x00\\x00puedeq\\x01X\\x03\\x00\\x00\\x00serq\\x02}q\\x03(X\\t\\x00\\x00\\x00cualquierq\\x04KdX\\x04\\x00\\x00\\x00casiq\\x05]q\\x06X\\x04\\x00\\x00\\x00cosaq\\x07X\\x01\\x00\\x00\\x00!q\\x08\\x85q\\tue.'" - ] - }, - "execution_count": 84, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ - "información = ['puede', 'ser', {'casi': [], 'cualquier': 100, 'cosa': ('!',)}]\n", - "\n", - "import pickle\n", - "\n", - "pickle.dumps(información)" + "from matplotlib import pyplot" ] }, { "cell_type": "code", - "execution_count": 85, + "execution_count": null, "metadata": { "collapsed": false }, - "outputs": [ - { - "data": { - "text/plain": [ - "['puede', 'ser', {'casi': [], 'cosa': ('!',), 'cualquier': 100}]" - ] - }, - "execution_count": 85, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ - "# en sentido contrario\n", - "pickle.loads(_)" + "x = [0.1*i for i in range(-50, 51)]\n", + "y = [x_i**2 for x_i in x]" ] }, { "cell_type": "code", - "execution_count": 86, + "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ - "# O bien guardar directamente a un archivo\n", - "\n", - "pickle.dump(información, open('datos.pkl', 'wb'))" + "pyplot.plot(x,y)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Los gráficos emergentes son buenos porque tiene la barra de herramientas y podemos guardarlos en excelente calidad (incluso vectorial, ideal para un poster A0). Pero en los notebooks podemos poner los gráficos directamente incrustados" ] }, { "cell_type": "code", - "execution_count": 87, + "execution_count": null, "metadata": { "collapsed": false }, - "outputs": [ - { - "data": { - "text/plain": [ - "['puede', 'ser', {'casi': [], 'cosa': ('!',), 'cualquier': 100}]" - ] - }, - "execution_count": 87, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ - "pickle.load(open('datos.pkl', 'rb'))" + "pyplot.plot(x,y)\n", + "pyplot.title('Pará bola!')\n", + "pyplot.grid()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Siempre que la clase **sea serializable** (es decir, que se base en otras clases serializables), pickle permite serializar instancias de clases arbitrarias. " + "Matplotlib sabe hacer muchísimos tipos de gráficos!" ] }, { "cell_type": "code", - "execution_count": 91, + "execution_count": null, "metadata": { "collapsed": false }, - "outputs": [ - { - "data": { - "text/plain": [ - "b'\\x80\\x03c__main__\\nA\\nq\\x00)\\x81q\\x01}q\\x02X\\x05\\x00\\x00\\x00valorq\\x03X\\x08\\x00\\x00\\x00un valorq\\x04sb.'" - ] - }, - "execution_count": 91, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ - "class A:\n", - " \"una clase que no hace absolutamente nada\"\n", - " \n", - " def __init__(self, valor):\n", - " self.valor = valor\n", - " \n", - "\n", - "a = A('un valor')\n", - "\n", - "a_serializado = pickle.dumps(a)\n", - "a_serializado" + "components = [c for (c, f) in critical_oil[1:]]\n", + "fraction = [float(f) for (c, f) in critical_oil[1:]]\n", + "# el ; evita el output\n", + "pyplot.pie(fraction, labels=components, shadow=True);" ] }, { "cell_type": "code", - "execution_count": 89, + "execution_count": null, "metadata": { "collapsed": false }, - "outputs": [ - { - "data": { - "text/plain": [ - "bytes" - ] - }, - "execution_count": 89, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ - "type(a_serializado) # la serializados es como datos binarios \"crudos\"" + "import random\n", + "campana = [random.gauss(0, 0.5) for i in range(1000)]" ] }, { "cell_type": "code", - "execution_count": 92, + "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ - "b= pickle.loads(_)" + "pyplot.hist(campana, bins=15);" ] }, { - "cell_type": "code", - "execution_count": 95, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "data": { - "text/plain": [ - "False" - ] - }, - "execution_count": 95, - "metadata": {}, - "output_type": "execute_result" - } - ], + "cell_type": "markdown", + "metadata": {}, "source": [ - "a is b" + "Pero antes de seguir con Matplotlib debemos aprender el corazón del Python Cientifico: Numpy" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "El objeto reconstruído tiene *el mismo estado* (es identico) al original, pero no es en sí el mismo objeto" + "## Numpy, todo es un array\n", + "\n", + "El paquete **numpy** es usado en casi todos los cálculos numéricos usando Python. Es un paquete que provee a Python de estructuras de datos vectoriales, matriciales y de rango mayor, de alto rendimiento. Está implementado en C y Fortran, de modo que cuando los cálculos son vectorizados (formulados con vectores y matrices), el rendimiento es muy bueno." ] }, { @@ -1306,1050 +1526,756 @@ }, "outputs": [], "source": [ - "b is a" + "import numpy as np" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Un detalle importante: para poder deseralizar un objeto arbitrario, su clase debe existir en el espacio de nombres" + "El pilar de numpy (y toda la computación científica basada en Python) es el tipo de datos `ndarray`, o sea arreglos de datos multidimensionales. \n", + "\n", + "¿Otra secuencia más? ¿pero que tenina de malo las listas?\n", + "\n", + "Las listas son geniales pero guardar **cualquier tipo de objeto** y su flexibilidad las vuelve ineficientes" ] }, { "cell_type": "code", - "execution_count": 96, + "execution_count": null, "metadata": { "collapsed": false }, - "outputs": [ - { - "ename": "AttributeError", - "evalue": "Can't get attribute 'A' on ", - "output_type": "error", - "traceback": [ - "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[1;31mAttributeError\u001b[0m Traceback (most recent call last)", - "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[1;32mdel\u001b[0m \u001b[0mA\u001b[0m \u001b[1;31m# borramos la clase A del espacio de nombres global\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 2\u001b[1;33m \u001b[0mpickle\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mloads\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0ma_serializado\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[1;31mAttributeError\u001b[0m: Can't get attribute 'A' on " - ] - } - ], + "outputs": [], "source": [ - "del A # borramos la clase A del espacio de nombres global\n", - "pickle.loads(a_serializado)" + "%timeit [0.1*i for i in range(10000)] # %timeit es otra magia de ipython" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%timeit np.arange(0, 1000, .1) # arange es igual a range, pero soporta paso de tipo flotante" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "**pickle** es un tipo de serialización específica para Python. Una alternativa más genérica que muchos otros lenguajes soportan (y es muy típica para compartir datos a traves de \"APIs\" en la web) es el formato [JSON](https://es.wikipedia.org/wiki/JSON), que funciona igual, pero genera una serialización en formato texto y más legible por humanos" + "Existen varias formas para inicializar nuevos arreglos de numpy, por ejemplo desde\n", + "\n", + "- Listas o tuplas\n", + "- Usando funciones dedicadas a generar arreglos numpy, como `arange`, `linspace`,`ones`, `zeros` etc.\n", + "- Leyendo datos desde archivos" ] }, { "cell_type": "code", - "execution_count": 97, + "execution_count": null, "metadata": { "collapsed": false }, - "outputs": [ - { - "data": { - "text/plain": [ - "'[\"puede\", \"ser\", {\"cualquier\": 100, \"casi\": [], \"cosa\": [\"!\"]}]'" - ] - }, - "execution_count": 97, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ - "import json\n", - "\n", - "json.dumps(información)" + "v = np.array([1,2,3,4])\n", + "v" ] }, { - "cell_type": "markdown", - "metadata": {}, + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], "source": [ - "## Ejecutando otros \"programas\" desde jupyter y python\n", - "\n", - "Jupyter permite llamar a programas subyacentes preciendo el comando con un signo de exclamación " + "# una matriz: el argumento de la función array function es una lista anidada de Python\n", + "M = np.array([[1, 2], \n", + " [3, 4]])\n", + "M" ] }, { "cell_type": "code", - "execution_count": 98, + "execution_count": null, "metadata": { - "collapsed": true + "collapsed": false }, "outputs": [], "source": [ - "# !notepad en windows\n", - "!gedit # abre el programa gedit en linux " + "type(v), type(M)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Incluso podemos capturar la salida del comando y obtener una lista de textos" + "Los ndarrays tienen distintos atributos. Por ejemplo" ] }, { "cell_type": "code", - "execution_count": 100, + "execution_count": null, "metadata": { "collapsed": false }, - "outputs": [ - { - "data": { - "text/plain": [ - "IPython.utils.text.SList" - ] - }, - "execution_count": 100, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ - "mole = !cat pesos.csv | grep \"Mole\" \n", - "type(mole)" + "v.ndim, M.ndim # cantidad de dimensiones" ] }, { - "cell_type": "markdown", - "metadata": {}, + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], "source": [ - "Si queremos hacer esto en \"Python puro\", por ejemplo porque queremos que una función ejecute un programa \n", - "\n", - "debemos usar el módulo `subprocess`" + "v.shape, M.shape # tupla de \"forma\". len(v.shape) == v.ndim" ] }, { "cell_type": "code", - "execution_count": 101, + "execution_count": null, "metadata": { "collapsed": false }, - "outputs": [ - { - "data": { - "text/plain": [ - "0" - ] - }, - "execution_count": 101, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ - "import subprocess\n", - "\n", - "subprocess.call(['gedit'])" + "v.size, M.size # cantidad de elementos. " ] }, { "cell_type": "code", - "execution_count": 102, + "execution_count": null, "metadata": { "collapsed": false }, - "outputs": [ - { - "data": { - "text/plain": [ - "b'hola python, soy echo\\n'" - ] - }, - "execution_count": 102, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ - "subprocess.check_output(['echo', 'hola python, soy echo']) # se ejecuta en el \"kernel\" (ver consola)" + "M.T # transpuesta!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Más estructuras de datos!\n", - "\n" + "A diferencia de las listas, los *arrays* tambien **tienen un tipo homogéneo** " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "v.dtype # " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "El módulo [`collections`](https://docs.python.org/3.4/library/collections.html) tiene muchas otras clases complementarias a las listas, tuplas, diccionarios y conjuntos que ya vimos, útiles para propósitos específicos " + "Se puede definir explicitamente el tipo de datos del array" ] }, { "cell_type": "code", - "execution_count": 104, + "execution_count": null, "metadata": { - "collapsed": true + "collapsed": false }, "outputs": [], "source": [ - "from collections import Counter, OrderedDict, namedtuple #hay más!" + "np.array([[1, 2], [3, 4]], dtype=complex)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "OrderedDict es... un diccionario que sí queda ordenado" + "Una gran ventaja del atributo `shape` es que podemos cambiarlo. Es decir, reacomodar la distrución de los elementos (por supuesto, sin perderlos en el camino)" ] }, { "cell_type": "code", - "execution_count": 110, + "execution_count": null, "metadata": { "collapsed": false }, - "outputs": [ - { - "data": { - "text/plain": [ - "'Dictionary that remembers insertion order'" - ] - }, - "execution_count": 110, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], + "source": [ + "A = np.arange(0, 12)\n", + "print(A)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], "source": [ - "OrderedDict.__doc__ # para http://twitter.com/Obvio" + "A.shape = 3, 4\n", + "print(A)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Esto es porque numpy en general no mueve los elementos de la memoria y en cambio usa **vistas** para mostrar los elementos de distinta forma. Es importante entender esto porque incluso los slicings son vistas. " ] }, { "cell_type": "code", - "execution_count": 114, + "execution_count": null, "metadata": { "collapsed": false }, - "outputs": [ - { - "data": { - "text/plain": [ - "{'a': 12, 'b': 10}" - ] - }, - "execution_count": 114, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ - "d = dict()\n", - "d['a'] = 12\n", - "d['b'] = 10\n", - "d" + "a = np.arange(10)\n", + "b = a[::2] # todo de 2 en 2\n", + "b" ] }, { "cell_type": "code", - "execution_count": 115, + "execution_count": null, "metadata": { - "collapsed": false, - "scrolled": true + "collapsed": false }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "('item_1', 1)\n", - "('item_2', '1 millon')\n", - "('item_3', None)\n" - ] - } - ], + "outputs": [], "source": [ - "d = OrderedDict()\n", - "d['item_1'] = 1\n", - "d['item_2'] = '1 millon'\n", - "d['item_3'] = None\n", - "for par in d.items():\n", - " print(par)\n" + "b[0] = 12\n", + "a # chan!!!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "`Counter` recibe cualquier secuencia y cuenta los elementos " + "En cambio" ] }, { "cell_type": "code", - "execution_count": 105, + "execution_count": null, "metadata": { "collapsed": false }, - "outputs": [ - { - "data": { - "text/plain": [ - "Counter({'a': 5, 'b': 2, 'c': 1, 'd': 1, 'r': 2})" - ] - }, - "execution_count": 105, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ - "contador = Counter('abracadabra')\n", - "contador" + "a = np.arange(10)\n", + "b = a[::2].copy()\n", + "b[0] = 12\n", + "a" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Además de `arange` hay otras funciones que devuelven arrays. Por ejemplo `linspace`, que a diferencia de `arange` no se da el tamaño del paso, sino la cantidad de puntos que queremos en el rango" ] }, { "cell_type": "code", - "execution_count": 108, + "execution_count": null, "metadata": { "collapsed": false }, - "outputs": [ - { - "data": { - "text/plain": [ - "[('a', 5), ('b', 2)]" - ] - }, - "execution_count": 108, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ - "contador.most_common(2)" + "np.linspace(0, 2 * np.pi, 100) # por defecto, incluye el limite. " ] }, { "cell_type": "code", - "execution_count": 109, + "execution_count": null, "metadata": { "collapsed": false }, - "outputs": [ - { - "data": { - "text/plain": [ - "Counter({1: 3, 2: 2, 'hola': 1})" - ] - }, - "execution_count": 109, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ - "Counter([1, 2, 'hola', 1, 1, 2])" + "_.size # en cualquier consola, python guarda el ultimo output en la variable _ " ] }, { - "cell_type": "markdown", - "metadata": {}, + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], "source": [ - "`namedtuple` es una factory de \"tuplas con nombre\", es decir, nuevos tipos de dato que funcionan igual que una tupla, pero donde cada elemento puede tener un nombre además de su posición. \n" + "matriz_de_ceros = np.zeros((4,6))\n", + "matriz_de_ceros" ] }, { "cell_type": "code", - "execution_count": 118, + "execution_count": null, "metadata": { "collapsed": false }, - "outputs": [ - { - "data": { - "text/plain": [ - "Raices(x1=-0.6180339887498949, x2=1.618033988749895)" - ] - }, - "execution_count": 118, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ - "\n", - "Raices = namedtuple('Raices', ['x1', 'x2'])\n", - "\n", - "\n", - "def raices(a, b=0, c=0):\n", - " \"\"\"dados los coeficientes, encuentra los valores de x tal que ax^2 + bx + c = 0\"\"\"\n", - "\n", - " discriminante = (b**2 - 4*a*c)**0.5\n", - " x1 = (-b + discriminante)/(2*a)\n", - " x2 = (-b - discriminante)/(2*a)\n", - " return Raices(x1, x2)\n", - "\n", - "soluciones = raices(-2, 2, 2)\n", - "soluciones" + "np.ones((2, 4))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "En el ejemplo puede no ser necesario, pero si la tupla devuelva por la función tuviera muchos elementos (y no tenemos su código a la vista), **recordar qué significado tiene cada posición** puede ser engorroso. \n", + "Pero numpy no sólo nos brinda los arrays. Los conceptos claves que aporta son *vectorización* y *broadcasting*\n", "\n", - "Lo bueno es que usar una `namedtuple` no es disruptiva, porque sigue funcionando como una tupla " + "La **vectorización** describe la **ausencia de iteraciones explícitas e indización**\n", + "(que toman lugar, por supuesto, \"detrás de escena\", en un optimizado y precompilado\n", + "código C). La vectorización tiene muchas ventajas:\n", + "\n", + "* El código vectorizado es más conciso y fácil de leer.\n", + "* Menos líneas de código habitualmente implican menos errores.\n", + "* El código se parece más a la notación matemática estándar (por lo que es más fácil,\n", + "por lo general, corregir código asociado a construcciones matemáticas\n", + "* La vectorización redunda en un código más \"pythónico\"" ] }, { "cell_type": "code", - "execution_count": 120, + "execution_count": null, "metadata": { "collapsed": false }, - "outputs": [ - { - "data": { - "text/plain": [ - "1.618033988749895" - ] - }, - "execution_count": 120, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ - "soluciones[1]" + "a = np.array([3, 4.3, 1])\n", + "b = np.array([-1, 0, 3.4])\n", + "c = a * b\n", + "c" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Pero también se pueden pedir los valores como atributos" + "¡Basta de bucles `for` for todos lados! " ] }, { - "cell_type": "code", - "execution_count": 121, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "data": { - "text/plain": [ - "-0.6180339887498949" - ] - }, - "execution_count": 121, - "metadata": {}, - "output_type": "execute_result" - } - ], + "cell_type": "markdown", + "metadata": {}, "source": [ - "soluciones.x1" + "El **broadcasting** (*difusión*) es el término que describe el comportamiento\n", + "**elemento por elemento** de las operaciones. En general, en Numpy todas\n", + "las operaciones adoptan por defecto un comportamiento de este tipo (no sólo las operaciones\n", + "aritméticas sino las lógicas, las funcionales y las de nivel de bits). " ] }, { "cell_type": "code", - "execution_count": 122, + "execution_count": null, "metadata": { "collapsed": false }, - "outputs": [ - { - "data": { - "text/plain": [ - "1.618033988749895" - ] - }, - "execution_count": 122, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ - "soluciones.x2" + "x = np.linspace(-12, 12, 1000)\n", + "y = x ** 2 - 1\n", + "pyplot.plot(x, y)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Obviamente, como es una tupla (es inmutable), no podemos asignar los atributos" + "Matplotlib se lleva muy bien con numpy (de hecho lo usa internamente)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Slicing extendido\n", + "\n", + "El funcionamiento básico del indexado y el slicing funciona igual con `ndarrays` que con cualquier secuencia. \n" ] }, { "cell_type": "code", - "execution_count": 123, + "execution_count": null, "metadata": { "collapsed": false }, - "outputs": [ - { - "ename": "AttributeError", - "evalue": "can't set attribute", - "output_type": "error", - "traceback": [ - "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[1;31mAttributeError\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[0msoluciones\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mx1\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;36m10\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[1;31mAttributeError\u001b[0m: can't set attribute" - ] - } - ], + "outputs": [], "source": [ - "soluciones.x1 = 10" + "ruido = np.random.random(1000) # 1000 numeros aleatorios entre [0, 1)\n" ] }, { - "cell_type": "markdown", - "metadata": {}, + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], "source": [ - "### Traer datos de Internet\n", - "\n", - "La biblioteca estándar tiene funcionalidades para manejar (leer y escribir) muchos protocolos de internet: http, pop3, ftp, imap, smtp y más. \n", - "\n", - "Para trabajar extensivamente con http, es muy popular (y recomendado) un biblioteca alternativa no oficial llamado [requests](http://www.python-requests.org/en/latest/)\n", - "\n", - "También es útil el magic `%load` en el contexto de la sesión interactiva" + "ruido[0] == ruido[-1000]" ] }, { "cell_type": "code", - "execution_count": 125, + "execution_count": null, "metadata": { - "collapsed": true + "collapsed": false }, "outputs": [], "source": [ - "from urllib.request import urlopen " + "ruido[999] == ruido[-1]" ] }, { "cell_type": "code", - "execution_count": 126, + "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ - "url = 'https://gist.githubusercontent.com/mgaitan/d75956d1d928fb4a8c8d/raw/60085d8bc1468dca88c029da7fe88f5956310ae3/Hola.txt'\n", - "with urlopen(url) as response:\n", - " contenido = response.read().decode('utf8') # el decode es para \"decodificar\" bytes crudos como texto unicode" + "ruido[1:5]" ] }, { "cell_type": "code", - "execution_count": 127, + "execution_count": null, "metadata": { "collapsed": false }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Hola curso!\n", - "\n", - "\n", - "Los quiero mucho :D\n" - ] - } - ], + "outputs": [], "source": [ - "print(contenido)" + "ruido[0:10] = np.zeros((10,)) # claro que los arrays son mutables!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "#### Ejercicio\n", - "\n", - "1. Abrir la portada de un portal de noticias de su elección, leer todo su contenido y listar las 10 palabras más repetidas de más de 4 caracteres y que no contengan símbolos\n" + "Pero veamos algo más. Supongamos que tenemos una matriz de 3x3" ] }, { "cell_type": "code", - "execution_count": 134, + "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ - "simbolos = set(\"#$%&\\'()*+,-./:;<=>?@[\\]^_`{|}~\")" + "m = np.arange(0, 9) \n", + "m.shape = 3, 3\n", + "m" ] }, { "cell_type": "code", - "execution_count": 135, + "execution_count": null, "metadata": { - "collapsed": true + "collapsed": false }, "outputs": [], "source": [ - "url = 'http://www.lavoz.com.ar'\n", - "with urlopen(url) as response:\n", - " contenido = response.read().decode('utf8') # el decode es para \"decodificar\" bytes crudos como texto unicode" + "m[0] # primer indice: filas" ] }, { "cell_type": "code", - "execution_count": 139, + "execution_count": null, "metadata": { "collapsed": false }, - "outputs": [ - { - "data": { - "text/plain": [ - "{'#', 'a'}" - ] - }, - "execution_count": 139, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ - "set('#hola') & set('#dfdfdfa')" + "m[0:2]" ] }, { - "cell_type": "code", - "execution_count": 141, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "data": { - "text/plain": [ - "[('comun', 44),\n", - " ('clearfix\"', 40),\n", - " ('sinimagen', 23),\n", - " ('destacada', 19),\n", - " ('página', 14),\n", - " ('formato', 14),\n", - " ('segmentación', 14),\n", - " ('clearfix', 14),\n", - " ('sobre', 10),\n", - " ('galeria', 10)]" - ] - }, - "execution_count": 141, - "metadata": {}, - "output_type": "execute_result" - } - ], + "cell_type": "markdown", + "metadata": {}, "source": [ - "palabras = [palabra.lower() for palabra in contenido.split() if len(palabra) > 4 and not set(palabra) & simbolos]\n", - "\n", - "Counter(palabras).most_common(10)" + "Pero la sintaxis se extiende de una manera eficiente y compacta.\n", + "\n" ] }, { "cell_type": "code", - "execution_count": 142, + "execution_count": null, "metadata": { "collapsed": false }, - "outputs": [ - { - "ename": "ImportError", - "evalue": "No module named 'pyquery'", - "output_type": "error", - "traceback": [ - "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[1;31mImportError\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[1;32mfrom\u001b[0m \u001b[0mpyquery\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mPyQuery\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[1;31mImportError\u001b[0m: No module named 'pyquery'" - ] - } - ], + "outputs": [], "source": [ - "from pyquery import PyQuery" + "%timeit m[1][1] # buuuuh!!!" ] }, { - "cell_type": "markdown", - "metadata": {}, + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], "source": [ - "## Escribir programas de línea de comando\n", - "\n", - "\n", - "Ya vimos que es muy simple ejecutar un módulo de python como un **script**. Simplemente hay que pasar como parámetro al ejecutable python el módulo en cuestión \n", - "\n", - " python archivo.py\n" + "%timeit m[1,1] # yeaaaa!!!" ] }, { "cell_type": "code", - "execution_count": 145, + "execution_count": null, "metadata": { "collapsed": false }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Overwriting ejemplo_script.py\n" - ] - } - ], + "outputs": [], "source": [ - "%%writefile ejemplo_script.py\n", - "\n", - "saludo = \"Hola Terremoto!\"\n", - "\n", - "print(saludo)" + "m[:,0] # quiero la primer columna" ] }, { "cell_type": "code", - "execution_count": 146, + "execution_count": null, "metadata": { "collapsed": false }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Hola Terremoto!\r\n" - ] - } - ], + "outputs": [], "source": [ - "!python ejemplo_script.py" + "m[0:2, 0:2] # la submatriz superior izquierda de 2x2 " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "El tema es que si importamos ese módulo desde la sesión interactiva o desde otro módulo, tambien se ejecutará todo el código que defina" + "Se acuerdan que en el slicing común había un tercer parametro opcional que era el paso? Funciona acá también" ] }, { "cell_type": "code", - "execution_count": 147, + "execution_count": null, "metadata": { "collapsed": false }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Hola Terremoto!\n" - ] - } - ], + "outputs": [], "source": [ - "from ejemplo_script import saludoº" + "m[::2, ::2] # esquinas" ] }, { "cell_type": "code", - "execution_count": 148, + "execution_count": null, "metadata": { "collapsed": false }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Hola Terremoto!\n" - ] - } - ], + "outputs": [], + "source": [ + "a = np.arange(60)\n", + "a.shape = 6, 10\n", + "a[:,:6]\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], "source": [ - "sak" + "a[:,2:3]h" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "A veces queremos que **se ejecute algo sólo cuando lo invocamos como script** y no cuando lo importamos. \n", + "Como resumen\n", "\n", - "Para eso podemos valernos de que Python asigna el nombre `__main__` al módulo principal con que fue llamado, en la variable global `__name__`" + "![](http://www.tp.umu.se/~nylen/pylect/_images/numpy_indexing.png)\n" ] }, { - "cell_type": "code", - "execution_count": 149, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Overwriting ejemplo_script2.py\n" - ] - } - ], + "cell_type": "markdown", + "metadata": {}, "source": [ - "%%writefile ejemplo_script2.py\n", + "### Ejercicios\n", "\n", - "saludo = \"Hola Mundo\"\n", + "- Crear un array de 1000 números aleatorios y encontrar su media (tip: ver el método `mean()`)\n", + "- Crear una array (matriz) de 10x10 donde cada fila va del 0 al 9 (tip: ¿qué pasa al sumar un array 2d con otro 1d?)\n", + "- Crear una matriz de esta forma\n", "\n", - "if __name__ == '__main__':\n", - " # esto se ejecuta solo cuando el modulo se llama como script\n", - " # no cuando se importa desde otro modulo o desde la sesion interactiva\n", - " print(saludo)" + " array([[0, 0, 0, 0, 5],\n", + " [0, 0, 0, 4, 0],\n", + " [0, 0, 3, 0, 0],\n", + " [0, 2, 0, 0, 0],\n", + " [1, 0, 0, 0, 0]])\n", + " (tip: investigar la función `diag()` y `rot90()`\n" ] }, { "cell_type": "code", - "execution_count": 150, + "execution_count": null, "metadata": { "collapsed": false }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Hola Mundo\r\n" - ] - } - ], + "outputs": [], "source": [ - "!python ejemplo_script2.py" + "aleatorio = np.random.normal?" ] }, { "cell_type": "code", - "execution_count": 151, + "execution_count": null, "metadata": { - "collapsed": false + "collapsed": true }, "outputs": [], "source": [ - "from ejemplo_script2 import saludo" + "aleatorio = np.random.normal" ] }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": { "collapsed": false }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Hola Mundo\r\n" - ] - } - ], + "outputs": [], "source": [ - "!python ejemplo_script2.py" + "np.zeros((10,10)) + np.arange(10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Si bien un programa de linea de comandos puede solicitar información al usuario interactivamente (por ejemplo, a utilizando la función `input()`), lo más típico es que los argumentos se pasen directamente en la llamada\n", + "### Algunas funciones incluídas en numpy\n", "\n", - " python mi_programa.py [parametro 2]\n", - " \n", - " \n", - "Python guarda todos los argumentos pasados (incluyendo el nombre del propio módulo) en una lista llamada `argv` del módulo `sys`" + "Encontrar raices de un polinomio" ] }, { "cell_type": "code", - "execution_count": 166, + "execution_count": null, "metadata": { "collapsed": false }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Overwriting ejemplo_argv.py\n" - ] - } - ], + "outputs": [], "source": [ - "%%writefile ejemplo_argv.py\n", - "\n", - "if __name__ == '__main__':\n", - " import sys\n", - " print(sys.argv)\n", - " print(sys.argv[2] * int(sys.argv[1]))\n", - " " + "np.roots([2, 0, -2])" ] }, { "cell_type": "code", - "execution_count": 170, + "execution_count": null, "metadata": { "collapsed": false }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "['ejemplo_argv.py', '80', '_']\r\n", - "________________________________________________________________________________\r\n" - ] - } - ], + "outputs": [], "source": [ - "!python ejemplo_argv.py 80 _" + "np.roots([1j, -4+0.4j, 18, -np.pi, 0]) # polinomio de grado 5!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Para parámetros muy simples podemos buscar valores directamente en esta lista, por ejemplo:\n", - "\n", - " if '--allthenigh' in sys.argv:\n", - " room.append(cristal)\n", - " \n", - "Pero la mayoría de las veces los argumentos posibles son más complejos y se requiere una **librería para procesar los argumentos** dados, convertirlos a un tipo de datos particular, asignar valores defaults a aquellos parametros que no se explicitaron, generar un resumen de la opciones disponibles a modo de ayuda, etc. \n", - "\n", - "Para esto se puede usar el módulo [`argparse`](https://docs.python.org/3/library/argparse.html#module-argparse)\n", - "\n", - "\n" + "Resolver un sistema de ecuaciones lineales `Ax = b`" ] }, { "cell_type": "code", - "execution_count": 171, + "execution_count": null, "metadata": { "collapsed": false }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Overwriting prog.py\n" - ] - } - ], + "outputs": [], "source": [ - "%%writefile prog.py\n", - "\n", - "import argparse\n", - "\n", - "if __name__ == '__main__':\n", - "\n", - " parser = argparse.ArgumentParser(description='Procesa una lista de enteros')\n", - " parser.add_argument('enteros', metavar='N', type=int, nargs='+', # uno o mas argumentos. se acumulan en una lista\n", - " help='an integer for the accumulator')\n", - " parser.add_argument('--sum', dest='operacion', action='store_const', # si se pasa --sum se usará const \n", - " const=sum, default=max, # en vez de default\n", - " help='sum the integers (default: find the max)')\n", - "\n", - " args = parser.parse_args()\n", - " print(args.operacion(args.enteros))" + "A = np.array([[1, 2], [0.5, -2]])\n", + "b = np.array([4, 5.2])" ] }, { "cell_type": "code", - "execution_count": 176, + "execution_count": null, "metadata": { "collapsed": false }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "72\r\n" - ] - } - ], + "outputs": [], + "source": [ + "x = np.linalg.solve(A, b)\n", + "x" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, "source": [ - "!python3 prog.py --sum 10 4 56 2 " + "Encontrar la inversa de una matriz" ] }, { "cell_type": "code", - "execution_count": 177, + "execution_count": null, "metadata": { "collapsed": false }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "usage: prog.py [-h] [--sum] N [N ...]\r\n", - "\r\n", - "Procesa una lista de enteros\r\n", - "\r\n", - "positional arguments:\r\n", - " N an integer for the accumulator\r\n", - "\r\n", - "optional arguments:\r\n", - " -h, --help show this help message and exit\r\n", - " --sum sum the integers (default: find the max)\r\n" - ] - } - ], + "outputs": [], "source": [ - "!python3 prog.py -h" + "A = np.array([[1,2],[3,4]])\n", + "invA = np.linalg.inv(A)\n", + "invA" ] }, { "cell_type": "code", - "execution_count": 178, + "execution_count": null, "metadata": { "collapsed": false }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "usage: prog.py [-h] [--sum] N [N ...]\r\n", - "prog.py: error: unrecognized arguments: 45\r\n" - ] - } - ], + "outputs": [], "source": [ - "!python3 prog.py 10 2 --sum" + "np.dot(A,invA) # producto punto" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ + "### Ejercicios\n", "\n", - "Tarea: Estudiar la biblioteca estándar de Python ! \n", - "\n", - "--------------\n", - "\n", + "- Encontrar las raices para el polinomio $$f(x) = \\frac{1}{4}(x^3 + 3x^2 − 6x − 8)$$ y grafique con x entre [-3, 3]\n", + "- Resuelva el siguiente sistema de ecuaciones \n", "\n", + " $$\\begin{array} - -x + z = -2\\\\ 2x - y + z = 1 \\\\ -3x + 2y -2z = -1 \\\\ x - 2y + 3z = -2 \\end{array}$$\n", "\n" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [] } ], "metadata": { diff --git a/Clase 4.ipynb b/Clase 4.ipynb index 0693d2b..6177b11 100644 --- a/Clase 4.ipynb +++ b/Clase 4.ipynb @@ -4,146 +4,1644 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Introducción a Python para ciencias e ingenierías (notebook 3)\n", + "# Introducción a Python para ciencias e ingenierías (notebook 4)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Ing. Martín Gaitán\n", + "\n", + "Twitter: `@tin_nqn_`\n", + "\n", + "** Registrá tu asistencia a esta clase **\n", + "### http://goo.gl/forms/olbkNwX700\n", "\n", + "**Links útiles**\n", "\n", - "Ing. Martín Gaitán (Phasety)\n", + "Repositorio del curso:\n", "\n", + "### http://bit.ly/cursopy\n", "\n", - "![](img/logo_small.png)\n", + "Python \"temporal\" online:\n", "\n", - "--------\n" + "### http://try.jupyter.org\n", + "\n", + "- Descarga de [Python \"Anaconda\"](http://continuum.io/downloads#py34)\n", + "- Resumen de [sintaxis markdown](https://github.com/jupyter/strata-sv-2015-tutorial/blob/master/resources/Working%20With%20Markdown%20Cells.ipynb)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Veamos un poco más de numpy" + "\n", + "## Matplotlib, un gráfico vale más que mil palabras" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Python es un lenguaje muy completo pero aunque es muy grande, su librería estándar no es infinita. Por suerte hay miles y miles de bibliotecas extra para complementar casi cualquier aspecto en el que queramos aplicar Python. En algunos ámbitos, con soluciones muy destacadas.\n", + "\n", + "Para hacer gráficos existe Matplotlib http://matplotlib.org/ . Ya viene instalado con la versión completa de Anaconda." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "%matplotlib inline" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { - "collapsed": false + "collapsed": true }, "outputs": [], "source": [ - "import numpy as np" + "from matplotlib import pyplot" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "x = [0.1*i for i in range(-50, 51)]\n", + "y = [x_i**2 for x_i in x]" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "pyplot.plot(x,y)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "`diag` pone el array dado en diagonal ascendente completando el resto con ceros" + "Los gráficos emergentes son buenos porque tiene la barra de herramientas y podemos guardarlos en excelente calidad a golpe de mouse. Pero en los notebooks podemos poner los gráficos directamente incrustados" ] }, { "cell_type": "code", - "execution_count": 86, + "execution_count": 29, "metadata": { "collapsed": false }, "outputs": [ { "data": { + "image/png": "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\n", "text/plain": [ - "array([[4, 0, 0, 0],\n", - " [0, 3, 0, 0],\n", - " [0, 0, 2, 0],\n", - " [0, 0, 0, 1]])" + "" ] }, - "execution_count": 86, "metadata": {}, - "output_type": "execute_result" + "output_type": "display_data" } ], "source": [ - "a = np.diag([1,2,3,4])\n", - "np.rot90(a, k=2)" + "pyplot.plot(x,y)\n", + "pyplot.title('Pará bola!')\n", + "pyplot.scatter([0], [15])\n", + "pyplot.annotate(s='un punto', xy=(0, 15), xytext=(0.3, 15.2))\n", + "pyplot.grid()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Podemos decirle qué diagonal con un offset entero" + "Matplotlib sabe hacer muchísimos tipos de gráficos!" ] }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 26, "metadata": { "collapsed": false }, "outputs": [ { "data": { + "image/png": "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\n", "text/plain": [ - "array([[0, 1, 0, 0],\n", - " [0, 0, 2, 0],\n", - " [0, 0, 0, 3],\n", - " [0, 0, 0, 0]])" + "" ] }, - "execution_count": 8, "metadata": {}, - "output_type": "execute_result" + "output_type": "display_data" } ], "source": [ - "np.diag([1,2,3], k=1)" + "import csv\n", + "\n", + "with open('data/near_critical_oil.csv') as csv_file:\n", + " reader = csv.reader(csv_file)\n", + " critical_oil = [line for line in reader] #o list(reader)\n", + "\n", + "components = [c for (c, f) in critical_oil[1:]]\n", + "fraction = [float(f) for (c, f) in critical_oil[1:]]\n", + "# el ; evita el output de la celda\n", + "pyplot.pie(fraction, labels=components, shadow=True);" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "import random\n", + "campana = [random.gauss(0, 0.5) for i in range(1000)]" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXkAAAEACAYAAABWLgY0AAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAFC5JREFUeJzt3X+MZed91/H3B/8oDSlZlkTrn8EO9SrZyg2xGseFgG/T\nxnKqyjZ/EDsSrUlpqHBL0go13U0hHgkpOOFXCsV/NTZbaBat0mCtIQ5eG18wSmO31E6crJf1oi54\n3ewkpDa0aiOv8Zc/5uxmOp2f556Ze+eZ90sa+Zxzz33u18/e+5lnnnt+pKqQJLXpT0y7AEnS5jHk\nJalhhrwkNcyQl6SGGfKS1DBDXpIatmrIJ7kvyXySZxZtuz7Jk0meSvIbSd6+6LEDSZ5LcjzJTZtZ\nuCRpbWuN5O8Hbl6y7RPA36+qtwEf7dZJsg+4HdjXPefeJP6lIElTtGoIV9XjwItLNn8NeF23vAt4\noVu+FThUVWer6hRwErh+uFIlSRt1YY/n7Af+a5J/zMIvie/vtl8GfHHRfqeByycrT5I0iT7TKZ8C\nPlhVbwR+FrhvlX29ZoIkTVGfkfz1VfVD3fJngF/ull8Arly03xV8eyrnvCQGvyT1UFXZ6HP6jORP\nJrmxW34XcKJbPgLckeTiJFcD1wBPrlDotv25++67p16D9U+/Duvffj/bufaq/mPjVUfySQ4BNwKv\nT/I8C0fT/C3gXyb5DuAPu3Wq6liSw8Ax4BXgrpqkMknSxFYN+ap63woPvWOF/T8GfGzSoiRJw/A4\n9g0ajUbTLmEi1j9d1j8927n2SWSrZ1SSOIsjSRuUhNqiL14lSduEIS9JDTPkJalhhrwkNcyQl6SG\nGfKS1LA+166RpiLZ8NFja/JwXrXOkNc2M2QoD/9LQ5o1TtdIUsMMeUlqmCEvSQ0z5CWpYYa8JDXM\nkJekhq0a8knuSzKf5Jkl2/9OkmeTfCXJxxdtP5DkuSTHk9y0WUVLktZnrePk7wf+BfAr5zYk+QHg\nFuB7q+pskjd02/cBtwP7gMuBR5LsrapXN6VySdKaVh3JV9XjwItLNv9t4B9W1dlun290228FDlXV\n2ao6BZwErh+2XEnSRvSZk78G+CtJvphknOT7uu2XAacX7XeahRG9JGlK+lzW4ELgz1TVDUneDhwG\n3rTCvsuegz43N3d+eTQa7dh7L0rSSsbjMePxeOJ21rzHa5KrgAer6tpu/SHgnqr6z936SeAG4CcA\nquqebvvngbur6okl7XmPV/WycIGyYa9d43tR28VW3uP1AeBd3YvuBS6uqv8NHAHuSHJxkqtZmNZ5\nskf7kqSBrDpdk+QQcCPwZ5M8D3wUuA+4rzus8mXgxwCq6liSw8Ax4BXgLofsO9dmXBZY0satOV0z\n+As6XbMjDD+1AguXBna6RjvTVk7XSJK2CUNekhpmyEtSwwx5SWqYIS9JDTPkJalhhrwkNcyQl6SG\nGfKS1DBDXpIaZshLUsMMeUlqmCEvSQ0z5CWpYYa8JDXMkJekhq0a8knuSzLf3QVq6WN/N8mrSXYv\n2nYgyXNJjie5aTMKliSt31oj+fuBm5duTHIl8G7gfy7atg+4HdjXPefeJP6lIElTtGoIV9XjwIvL\nPPRPgQ8v2XYrcKiqzlbVKeAkcP0QRUqS+tnwSDvJrcDpqvrykocuA04vWj8NXD5BbZKkCV24kZ2T\nvAb4CAtTNec3r/KUZe+SPDc3d355NBoxGo02UoY0mIUbjg/HG4NrKOPxmPF4PHE7WetNmeQq4MGq\nujbJtcAjwB90D18BvAC8A3g/QFXd0z3v88DdVfXEkvbKD0L7FsJz6H/nodscvj3f29osSaiqDY9K\nNjRdU1XPVNWeqrq6qq5mYUrmuqqaB44AdyS5OMnVwDXAkxstSJI0nLUOoTwEfAHYm+T5JO9fssv5\nYUtVHQMOA8eAh4C7HLJL0nStOV0z+As6XbMjOF0jDWtLpmskSduLIS9JDTPkJalhhrwkNcyQl6SG\nGfKS1DBDXpIaZshLUsMMeUlqmCEvSQ0z5CWpYYa8JDXMkJekhhnyktQwQ16SGmbIS1LD1roz1H1J\n5pM8s2jbP0rybJIvJflsktcteuxAkueSHE9y02YWLkla21oj+fuBm5dsexj4nqp6K3ACOACQZB9w\nO7Cve869SfxLQZKmaNUQrqrHgReXbDtaVa92q08AV3TLtwKHqupsVZ0CTgLXD1uuJGkjLpzw+T8O\nHOqWLwO+uOix08DlE7avLbJwT1ZJrekd8kl+AXi5qj69ym7L3tV4bm7u/PJoNGI0GvUtQ4Ma+ibZ\nkvoaj8eMx+OJ28lad5dPchXwYFVdu2jb3wA+APxgVX2r27YfoKru6dY/D9xdVU8saa+8o/3sWRjJ\nDx3yQ/87z3qNwfe2NksSqmrDo6cNfzGa5Gbg54BbzwV85whwR5KLk1wNXAM8udH2JUnDWXW6Jskh\n4Ebg9UmeB+5m4Wiai4Gj3Tzur1fVXVV1LMlh4BjwCnCXQ3ZJmq41p2sGf0Gna2aS0zXDtOd7W5tl\ny6ZrJEnbhyEvSQ0z5CWpYYa8JDXMkJekhhnyktQwQ16SGmbIS1LDDHlJapghL0kNm/R68poSr/8u\naT0M+W3N679LWp3TNZLUMENekhpmyEtSw1YN+ST3JZlP8syibbuTHE1yIsnDSXYteuxAkueSHE9y\n02YWLkla21oj+fuBm5ds2w8craq9wKPdOkn2AbcD+7rn3JvEvxQkaYpWDeGqehx4ccnmW4CD3fJB\n4LZu+VbgUFWdrapTwEng+uFKlSRtVJ+R9p6qmu+W54E93fJlwOlF+50GLp+gNknShCaaTulu1rra\nwdre8FKSpqjPyVDzSS6pqjNJLgW+3m1/Abhy0X5XdNv+mLm5ufPLo9GI0WjUowxJatd4PGY8Hk/c\nTta6u3ySq4AHq+rabv0TwDer6uNJ9gO7qmp/98Xrp1mYh78ceAT47lryAkmWblIPC5c1GPqM11lu\nbzPaHL4939vaLEmoqg2fmr7qSD7JIeBG4PVJngc+CtwDHE7yN4FTwHsBqupYksPAMeAV4C7TXJKm\na82R/OAv6Eh+EI7kZ7M939vaLJsykpe0MUNfHdRfGpqUIS8NyiuDarZ4RqokNcyQl6SGGfKS1DBD\nXpIaZshLUsMMeUlqmCEvSQ0z5CWpYYa8JDXMkJekhhnyktQwQ16SGmbIS1LDDHlJaljvkE9yIMlX\nkzyT5NNJviPJ7iRHk5xI8nCSXUMWK0namF4h39339QPAdd29Xy8A7gD2A0erai/waLcuSZqSviP5\n/wucBV6T5ELgNcDvALcAB7t9DgK3TVyhJKm3XiFfVb8L/BPgf7EQ7i9V1VFgT1XNd7vNA3sGqVKS\n1Evf6Zo/D/wMcBVwGfDaJH998T7d3bq9QaUkTVHfe7x+H/CFqvomQJLPAt8PnElySVWdSXIp8PXl\nnjw3N3d+eTQaMRqNepYhSW0aj8eMx+OJ20mfu8EneSvwq8DbgW8B/wp4EvhzwDer6uNJ9gO7qmr/\nkueWd6CfXBKGv2n0LLe3GW3Ofnt+VnROEqpqw3d37xXy3Qt+GLgTeBX4LeAngO8CDgNvBE4B762q\nl5Y8z5AfgCG/M9rzs6Jztjzk+zLkh2HI74z2/KzonL4h7xmvktQwQ16SGmbIS1LDDHlJapghL0kN\nM+QlqWGGvCQ1zJCXpIYZ8pLUMENekhpmyEtSwwx5SWqYIS9JDTPkJalhhrwkNcyQl6SG9Q75JLuS\nfCbJs0mOJXlHkt1JjiY5keThJLuGLFaStDGTjOR/EfhcVb0F+F7gOLAfOFpVe4FHu3VJ0pT0vZH3\n64CnqupNS7YfB26sqvkklwDjqnrzkn28/d8AvP3fzmjPz4rO6Xv7vwt7vt7VwDeS3A+8FfhvwM8A\ne6pqvttnHtjTs31JnPtlPhx/aew8fUP+QuA64Ker6jeSfJIlUzNVVUmWfUfNzc2dXx6NRoxGo55l\nSK0b+i8NbRfj8ZjxeDxxO32nay4Bfr2qru7W3wkcAN4E/EBVnUlyKfCY0zWbw+ka2+vTnp+97avv\ndE2vL16r6gzwfJK93aYfAr4KPAjc2W27E3igT/uSpGH0GskDJHkr8MvAxcD/AN4PXAAcBt4InALe\nW1UvLXmeI/kBOJK3vT7t+dnbvvqO5HuHfF+G/DAMedvr056fve1rS6drJEnbgyEvSQ0z5CWpYYa8\nJDXMkJekhhnyktQwQ16SGmbIS1LDDHlJapghL0kNM+QlqWGGvCQ1zJCXpIYZ8pLUsL63/9MGDX2v\nTklaD0N+S3m/Tklba6LpmiQXJHkqyYPd+u4kR5OcSPJwkl3DlClJ6mPSOfkPAcf49hB1P3C0qvYC\nj3brkqQp6R3ySa4AfpiF+7yemzu4BTjYLR8EbpuoOknSRCYZyf8z4OeAVxdt21NV893yPLBngvYl\nSRPq9cVrkh8Bvl5VTyUZLbdPVVWSZb9pnJubO788Go0YjZZtQpJ2rPF4zHg8nrid9Ll7e5KPAT8K\nvAL8SeBPA58F3g6MqupMkkuBx6rqzUueWzvxjvELh1AOfXTNTmpvM9rcee3txM9eK5JQVRs+rK7X\ndE1VfaSqrqyqq4E7gP9UVT8KHAHu7Ha7E3igT/uSpGEMdcbrueHBPcC7k5wA3tWtS5KmpNd0zUQv\n6HTNUC3usPY2o82d195O/Oy1ou90jWe8SjvIZlxew18cs82Ql3aUzfjrSrPMq1BKUsMMeUlqmCEv\nSQ0z5CWpYYa8JDXMkJekhhnyktQwQ16SGmbIS1LDDHlJapghL0kNM+QlqWFeoGwZm3GlPkmaBkN+\nRV6tT9L212u6JsmVSR5L8tUkX0nywW777iRHk5xI8nCSXcOWK0naiL5z8meBn62q7wFuAH4qyVuA\n/cDRqtoLPNqtS5KmpO+NvM9U1dPd8u8DzwKXA7cAB7vdDgK3DVGkJKmfiY+uSXIV8DbgCWBPVc13\nD80DeyZtX5LU30RfvCZ5LfBrwIeq6vcWH5VSVZVk2W8v5+bmzi+PRiNGo9EkZUhSc8bjMePxeOJ2\n0vcmvEkuAv498FBVfbLbdhwYVdWZJJcCj1XVm5c8r2b9xr8Lv6w24+iaIdvcae1tRpu2N0Sbs/55\nbkUSqmrDh+n1PbomwKeAY+cCvnMEuLNbvhN4oE/7kqRh9BrJJ3kn8F+AL/PtocEB4EngMPBG4BTw\n3qp6aclzHcnb3oy0aXtDtDnrn+dW9B3J956u6cuQt73ZadP2hmhz1j/PrdjS6RpJ0vZgyEtSwwx5\nSWqYIS9JDWviKpReGliSltdEyC8Y+igESdr+nK6RpIY1NJKXNA1DT5d63P2wphLye/Z89zReVtKm\ncKp0lk3ljFf4ReCHB2rxV4B/wHY4M3C2a5z19jajTdubvTY9g3Ylfc94ndJ0zSXAUKP5NwzUjiS1\nxy9eJalhhrwkNcyQl6SGGfKS1LDBQz7JzUmOJ3kuyc8P3b4krVeSwX+2m0FDPskFwC8BNwP7gPcl\necuQrzF942kXMKHxtAuY0HjaBUxoPO0CJjTe9FcYPpCr+3ls0XLfn+1n6JH89cDJqjpVVWeBfwvc\nOvBrTNl42gVMaDztAiY0nnYBExpPu4AJjbfgNSYN4pVCebz5pc+goUP+cuD5Reunu22SpCkY+mSo\ndf09853f+XEuuuhfD/KCL7/823zrW4M0JUnNGfSyBkluAOaq6uZu/QDwalV9fNE+23NiS5KmrM9l\nDYYO+QuB/w78IPA7wJPA+6rq2cFeRJK0boNO11TVK0l+GviPwAXApwx4SZqeLb8KpSRp62z6Ga9J\n/lqSryb5f0muW2W/U0m+nOSpJE9udl3rtYH6Z/IksCS7kxxNciLJw0l2rbDfTPX/evozyT/vHv9S\nkrdtdY2rWav+JKMk/6fr76eS/L1p1LmcJPclmU/yzCr7zGTfr1X7LPc7QJIrkzzWZc5Xknxwhf3W\n3/9Vtak/wJuBvSyciXDdKvv9NrB7s+vZjPpZmJo6CVwFXAQ8Dbxl2rV3tX0C+HC3/PPAPbPe/+vp\nTxZuSPC5bvkdwBenXfcG6x8BR6Zd6wr1/2XgbcAzKzw+y32/Vu0z2+9dfZcAf6Fbfi0L33FO9N7f\n9JF8VR2vqhPr3H3mzhleZ/2zfBLYLcDBbvkgcNsq+85K/6+nP8//f1XVE8CuJHu2tswVrff9MCv9\n/UdU1ePAi6vsMrN9v47aYUb7HaCqzlTV093y7wPPApct2W1D/T9LFygr4JEkv5nkA9MuZoNm+SSw\nPVU13y3PAyu9GWap/9fTn8vtc8Um17Ve66m/gL/Y/bn9uST7tqy6yc1y369l2/R7kqtY+KvkiSUP\nbaj/Bzm6JslRFv7MWOojVfXgOpv5S1X1tSRvAI4mOd79Vt50A9Q/1W+vV6n/FxavVFWtcp7C1Pp/\nGevtz6Ujslk5imA9dfwWcGVV/UGS9wAPsDAtuF3Mat+vZVv0e5LXAp8BPtSN6P/YLkvWV+z/QUK+\nqt49QBtf6/77jST/joU/ebckZAao/wXgykXrV7Lw23VLrFZ/9yXUJVV1JsmlwNdXaGNq/b+M9fTn\n0n2u6LbNgjXrr6rfW7T8UJJ7k+yuqt/dohonMct9v6rt0O9JLgJ+Dfg3VfXAMrtsqP+3erpm2bmw\nJK9J8l3d8p8CbgJW/GZ/ilaay/tN4JokVyW5GLgdOLJ1Za3qCHBnt3wnCyOXP2IG+389/XkE+DE4\nf6b1S4umpaZtzfqT7El3mcQk17NwOPPMBM0aZrnvVzXr/d7V9ingWFV9coXdNtb/W/Bt8V9lYf7o\nD4EzwEPd9suA/9Atv4mFIxCeBr4CHJj2t9wbqb9bfw8L34SfnLH6dwOPACeAh4Fd26H/l+tP4CeB\nn1y0zy91j3+JVY7cmsX6gZ/q+vpp4AvADdOueVHth1g4Y/3l7r3/49ul79eqfZb7vavvncCrXX1P\ndT/vmaT/PRlKkho2S0fXSJIGZshLUsMMeUlqmCEvSQ0z5CWpYYa8JDXMkJekhhnyktSw/w+N7Mvd\n55g0gAAAAABJRU5ErkJggg==\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "pyplot.hist(campana, bins=15);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "El método `reshape` es otra manera de definir la forma de un array, generando uno nuevo array (a diferencia de `A.shape` que simplemente es otra vista del mismo array)" + "### La \"papa\" de matplotlib\n", + "\n", + " **Este es el algoritmo más importante para graficar con matplotlib**\n", + "\n", + "\n", + "1. Ir a http://matplotlib.org/gallery\n", + "2. Elegir el gráfico de ejemplo que más se parezca a lo que queremos lograr\n", + "3. Copiar el código del ejemplo y adaptarlo a nuestros datos y gustos\n", + "\n", + "![](files/img/lo_importante.png)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Ejercicios\n", + "\n", + "1. Dada la función para el cálculo de raices de una ecuación de segundo grado [implementada](https://gist.githubusercontent.com/mgaitan/cb0ad9778453607acb49/raw/8d85d2184a4b46b48440cf5b5d95062801a08cce/baskara.py) en clases anteriores, crear una función que dados los coeficientes grafique la parábola y denote las raices con puntos rojos y el valor de X en cada una. \n", + "\n", + "2. Basado en el [ejemplo de grafico de torta](http://matplotlib.org/examples/pie_and_polar_charts/pie_demo_features.html) de la galería, adaptar el ejemplo que grafica \"near_critical_oil.csv\" para que no se vea \"ovoide\" y la porción correspondiente a \"C2\" quede separada. Agregar un título al gráfico\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Antes de seguir con Matplotlib debemos aprender el corazón del Python Cientifico: **Numpy**" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Numpy, todo es un array" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "El paquete **numpy** es usado en casi todos los cálculos numéricos usando Python. Es un paquete que provee a Python de estructuras de datos vectoriales, matriciales y de rango mayor, de alto rendimiento. Está implementado en C y Fortran, de modo que cuando los cálculos son vectorizados (formulados con vectores y matrices), el rendimiento es muy bueno." + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "import numpy as np" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "El pilar de numpy (y toda la computación científica basada en Python) es el tipo de datos `ndarray`, o sea arreglos de datos multidimensionales.\n", + "\n", + "¿Otra secuencia más? ¿pero que tenían de malo las listas?\n", + "\n", + "Las listas son geniales paro guardar **cualquier tipo de objeto**, pero esa flexibilidad las vuelve ineficientes cuando lo que queremos es almacenar datos homogéneos" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1000 loops, best of 3: 1.03 ms per loop\n" + ] + } + ], + "source": [ + "%timeit [0.1*i for i in range(10000)] # %timeit es otra magia de ipython" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "10000 loops, best of 3: 37.2 µs per loop\n" + ] + } + ], + "source": [ + "%timeit np.arange(0, 1000, .1) # arange es igual a range, pero soporta paso de tipo flotante y devuelve un array" ] }, { "cell_type": "code", - "execution_count": 89, + "execution_count": 45, "metadata": { "collapsed": false }, "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1 loops, best of 3: 939 ms per loop\n" + ] + }, { "data": { "text/plain": [ - "array([[0, 1, 2],\n", - " [3, 4, 5],\n", - " [6, 7, 8]])" + "" ] }, - "execution_count": 89, + "execution_count": 45, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "A = np.arange(9).reshape((3,3))\n", - "A" + "%%timeit -o\n", + "X = range(10000000)\n", + "Y = range(10000000)\n", + "Z = [(x + y) for x,y in zip(X,Y)]" ] }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 46, "metadata": { "collapsed": false }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "10 loops, best of 3: 43 ms per loop\n" + ] + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 46, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "%%timeit -o\n", + "X = np.arange(10000000)\n", + "Y = np.arange(10000000)\n", + "Z = X + Y" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "21.835120069048784" + ] + }, + "execution_count": 47, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "__.best / _.best" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Existen varias formas para inicializar nuevos arrays de numpy, por ejemplo desde" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- Listas o tuplas\n", + "- Usando funciones dedicadas a generar arreglos numpy, como `arange`, `linspace`,`ones`, `zeros` etc.\n", + "- Leyendo datos desde archivos" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "v = np.array([1,2,3,4])\n", + "v" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# una matriz: el argumento de la función array function es una lista anidada de Python\n", + "M = np.array([[1, 2],\n", + " [3, 4]])\n", + "M" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "type(v), type(M)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Dimensiones, tamaño, tipo, forma\n", + "\n", + "Los ndarrays tienen distintos atributos. Por ejemplo" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "v.ndim, M.ndim # cantidad de dimensiones" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "v.shape, M.shape # tupla de \"forma\". len(v.shape) == v.ndim" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "v.size, M.size # cantidad de elementos." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "M.T # transpuesta!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "A diferencia de las listas, los *arrays* tambien **tienen un tipo homogéneo**" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "v.dtype #" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Se puede definir explicitamente el tipo de datos del array" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "np.array([[1, 2], [3, 4]], dtype=complex)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Una gran ventaja del atributo `shape` es que podemos cambiarlo. Es decir, reacomodar la distrución de los elementos (por supuesto, sin perderlos en el camino)" + ] + }, + { + "cell_type": "code", + "execution_count": 99, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])" + ] + }, + "execution_count": 99, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "A = np.arange(0, 12)\n", + "A" + ] + }, + { + "cell_type": "code", + "execution_count": 100, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[ 0, 1, 2, 3],\n", + " [ 4, 5, 6, 7],\n", + " [ 8, 9, 10, 11]])" + ] + }, + "execution_count": 100, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "A.shape = 3, 4\n", + "A" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "El método `reshape` es otra manera de definir la forma de un array, generando uno nuevo array (a diferencia de `A.shape` que simplemente es otra vista del mismo array)" + ] + }, + { + "cell_type": "code", + "execution_count": 101, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[ 0, 1, 2, 3],\n", + " [ 4, 5, 6, 7],\n", + " [ 8, 9, 10, 11]])" + ] + }, + "execution_count": 101, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "A = np.arange(12).reshape((3,4))\n", + "A" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Vistas\n", + "\n", + "Esto es porque numpy en general no mueve los elementos de la memoria y en cambio usa **vistas** para mostrar los elementos de distinta forma. Es importante entender esto porque incluso los slicings son vistas." + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([0, 2, 4, 6, 8])" + ] + }, + "execution_count": 49, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a = np.arange(10)\n", + "b = a[::2] # todo de 2 en 2\n", + "b" + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([12, 1, 2, 3, 4, 5, 6, 7, 8, 9])" + ] + }, + "execution_count": 50, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "b[0] = 12\n", + "a # chan!!!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "En cambio" + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])" + ] + }, + "execution_count": 51, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "c = np.arange(10)\n", + "d = c[::2].copy()\n", + "d[0] = 12\n", + "c" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Una forma de saber si un array es \"base\" o hereda los datos de otro array (es una vista), es verificar el atributo `base`" + ] + }, + { + "cell_type": "code", + "execution_count": 55, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 55, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "b.base is a and a.base is None" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Otras funciones constructuras de arrays\n", + "\n", + "\n", + "Además de `arange` hay otras funciones que devuelven arrays. Por ejemplo `linspace`, que a diferencia de `arange` no se da el tamaño del paso, sino la cantidad de puntos que queremos en el rango" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "np.linspace(0, 2 * np.pi, 100) # por defecto, incluye el limite." + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "_.size # en cualquier consola, python guarda el ultimo output en la variable _" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "matriz_de_ceros = np.zeros((4,6))\n", + "matriz_de_ceros" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "np.ones((2, 4))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Pero numpy no sólo nos brinda los arrays. Los conceptos claves que aporta son *vectorización* y *broadcasting*" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Vectorización\n", + "\n", + "La **vectorización** define que las operaciones aritméticas entre arrays de igual forma se realizan implicitamente **elemento a elemento**, y por lo tanto hay una **ausencia de iteraciones explícitas y de indización**. \n", + "La vectorización tiene muchas ventajas:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "* El código vectorizado es más conciso y fácil de leer.\n", + "* Menos líneas de código habitualmente implican menos errores.\n", + "* El código se parece más a la notación matemática estándar (por lo que es más fácil,\n", + "por lo general, corregir código asociado a construcciones matemáticas\n", + "* La vectorización redunda en un código más \"pythónico\"" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "a = np.array([3, 4.3, 1])\n", + "b = np.array([-1, 0, 3.4])\n", + "c = a * b\n", + "c" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "¡Basta de bucles `for` for todos lados!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Broadcasting\n", + "\n", + "\n", + "El **broadcasting** (*difusión*) es el término que describe el comportamiento de las operaciones con arrays de distinta forma. Con ciertas restricciones, se trata de que el array de menores dimensiones se \"difunde\" al más grande, siempre que tengan formas compatibles\n", + "\n", + "En Numpy todas las operaciones adoptan por defecto un comportamiento de este tipo (no sólo las operaciones\n", + "aritméticas sino las lógicas, las funcionales y las de nivel de bits)\n", + "\n", + "La forma más obvia de observar el broadcasting es cuando se opera un array con un escalar" + ] + }, + { + "cell_type": "code", + "execution_count": 67, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([ 2., 4., 6.])" + ] + }, + "execution_count": 67, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a = np.array([1., 2., 3.])\n", + "b = 2.\n", + "a * b" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "podemos interpretar que el escalar `b` es un array adimensional que \"se estira\" para ser compatible con las dimensiones de `a`\n", + "\n", + "![](files/img/image001.gif)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Regla general del broadcasting\n", + "\n", + " Dos arrays son compatibles para operar via *broadcasting* si sus dimensiones \n", + " (de atrás hacia adelante) son iguales o alguna es 1. \n", + "\n", + "\n", + "En otras palabras:\n", + "\n", + " Debe cumplirse que el `shape` de uno sea \"sufijo\" del `shape` del otro array (1 es comodin) \n" + ] + }, + { + "cell_type": "code", + "execution_count": 72, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "((4, 3), (3,))" + ] + }, + "execution_count": 72, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a = np.array([[ 0.0, 0.0, 0.0],\n", + " [10.0, 10.0, 10.0],\n", + " [20.0, 20.0, 20.0],\n", + " [30.0, 30.0, 30.0]])\n", + "b = np.array([1.0, 2.0, 3.0])\n", + "\n", + "a.shape, b.shape # son compatibles para broadcasting" + ] + }, + { + "cell_type": "code", + "execution_count": 73, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[ 1., 2., 3.],\n", + " [ 11., 12., 13.],\n", + " [ 21., 22., 23.],\n", + " [ 31., 32., 33.]])" + ] + }, + "execution_count": 73, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a + b" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![](files/img/image002.gif)" + ] + }, + { + "cell_type": "code", + "execution_count": 75, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "ename": "ValueError", + "evalue": "operands could not be broadcast together with shapes (4,) (3,) ", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mValueError\u001b[0m Traceback (most recent call last)", + "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[0;32m 3\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 4\u001b[0m \u001b[1;31m#fails\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 5\u001b[1;33m \u001b[0ma\u001b[0m \u001b[1;33m+\u001b[0m \u001b[0mb\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 6\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[1;31mValueError\u001b[0m: operands could not be broadcast together with shapes (4,) (3,) " + ] + } + ], + "source": [ + "a = np.array([0.0, 10.0, 20.0, 30.0])\n", + "b = np.array([1.0, 2.0, 3.0])\n", + "\n", + "#fails\n", + "a + b" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Pero podemos elevar la dimensionalidad de `a` (agregar una dimensión sin cambiar los elementos) para poder operar entre los dos arrays" + ] + }, + { + "cell_type": "code", + "execution_count": 108, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[ 1., 2., 3.],\n", + " [ 11., 12., 13.],\n", + " [ 21., 22., 23.],\n", + " [ 31., 32., 33.]])" + ] + }, + "execution_count": 108, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a = a.reshape((4,1)) # equivalente a a[:,np.newaxis]\n", + "b = np.array([1.0, 2.0, 3.0])\n", + "a + b" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![](files/img/image004.gif)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Slicing extendido" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "El funcionamiento básico del indexado y el slicing funciona con `ndarrays` igual que con cualquier secuencia." + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "ruido = np.random.random(1000) # 1000 numeros aleatorios entre [0, 1)" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "ruido[0] == ruido[-1000]" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "ruido[999] == ruido[-1]" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "ruido[1:5]" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "ruido[0:10] = np.zeros((10,)) # claro que los arrays son mutables!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Pero veamos algo más. Supongamos que tenemos una matriz de 3x3" + ] + }, + { + "cell_type": "code", + "execution_count": 103, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[0, 1, 2],\n", + " [3, 4, 5],\n", + " [6, 7, 8]])" + ] + }, + "execution_count": 103, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "m = np.arange(0, 9)\n", + "m.shape = 3, 3\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": 104, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([0, 1, 2])" + ] + }, + "execution_count": 104, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "m[0] # primer indice: filas" + ] + }, + { + "cell_type": "code", + "execution_count": 105, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[0, 1, 2],\n", + " [3, 4, 5]])" + ] + }, + "execution_count": 105, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "m[0:2]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Pero la sintaxis se extiende de una manera eficiente y compacta." + ] + }, + { + "cell_type": "code", + "execution_count": 106, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The slowest run took 56.00 times longer than the fastest. This could mean that an intermediate result is being cached \n", + "1000000 loops, best of 3: 224 ns per loop\n" + ] + } + ], + "source": [ + "%timeit m[1][1] # buuuuh!!!" + ] + }, + { + "cell_type": "code", + "execution_count": 107, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The slowest run took 61.51 times longer than the fastest. This could mean that an intermediate result is being cached \n", + "10000000 loops, best of 3: 110 ns per loop\n" + ] + } + ], + "source": [ + "%timeit m[1,1] # yeaaaa!!!" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "m[:,0] # quiero la primer columna" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "m[0:2, 0:2] # la submatriz superior izquierda de 2x2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Se acuerdan que en el slicing común había un tercer parametro opcional que era el paso? Funciona acá también" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "m[::2, ::2] # esquinas" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "a = np.arange(60)\n", + "a.shape = 6, 10\n", + "a[:,:6]" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "a[:,2:3]h" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Como resumen" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![](http://www.tp.umu.se/~nylen/pylect/_images/numpy_indexing.png)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Ejercicios" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- Crear un array de 1000 números aleatorios y encontrar su media (tip: ver el método `mean()`)\n", + "- Crear una array (matriz) de 10x10 donde cada fila va del 0 al 9 (tip: ¿qué pasa al sumar un array 2d con otro 1d?)\n", + "- Crear una matriz de esta forma" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " array([[0, 0, 0, 0, 5],\n", + " [0, 0, 0, 4, 0],\n", + " [0, 0, 3, 0, 0],\n", + " [0, 2, 0, 0, 0],\n", + " [1, 0, 0, 0, 0]])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " (tip: investigar la función `diag()` y `rot90()`" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "aleatorio = np.random.normal?" + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "aleatorio = np.random.normal" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "np.zeros((10,10)) + np.arange(10)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Algunas funciones incluídas en numpy" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Encontrar raices de un polinomio" + ] + }, + { + "cell_type": "code", + "execution_count": 79, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([-0.5+0.8660254j, -0.5-0.8660254j])" + ] + }, + "execution_count": 79, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "np.roots([2, 2, 2])" + ] + }, + { + "cell_type": "code", + "execution_count": 77, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([-3.01556495 -5.38277801e+00j, 2.43369801 +1.38394115e+00j,\n", + " 0.18186694 -1.16314504e-03j, 0.00000000 +0.00000000e+00j])" + ] + }, + "execution_count": 77, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "np.roots([1j, -4+0.4j, 18, -np.pi, 0]) # polinomio de grado 5!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Resolver un sistema de ecuaciones lineales `Ax = b`" + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "A = np.array([[1, 2], [0.5, -2]])\n", + "b = np.array([4, 5.2])" + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "x = np.linalg.solve(A, b)\n", + "x" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Encontrar la inversa de una matriz" + ] + }, + { + "cell_type": "code", + "execution_count": 81, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[-2. , 1. ],\n", + " [ 1.5, -0.5]])" + ] + }, + "execution_count": 81, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "A = np.array([[1,2],[3,4]])\n", + "invA = np.linalg.inv(A)\n", + "invA" + ] + }, + { + "cell_type": "code", + "execution_count": 83, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[ 1.00000000e+00, 1.11022302e-16],\n", + " [ 0.00000000e+00, 1.00000000e+00]])" + ] + }, + "execution_count": 83, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "np.dot(A,invA) # producto punto:\n", + " # equivalente a @ invA en py3.5" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Ejercicios" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- Encontrar las raices para el polinomio $$f(x) = \\frac{1}{4}(x^3 + 3x^2 − 6x − 8)$$ y grafique con x entre [-3, 3]\n", + "- Resuelva el siguiente sistema de ecuaciones" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " $$\\begin{array} - -x + z = -2\\\\ 2x - y + z = 1 \\\\ -3x + 2y -2z = -1 \\end{array}$$" + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Veamos un poco más de numpy" + ] + }, + { + "cell_type": "code", + "execution_count": 57, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "import numpy as np" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`diag` pone el array dado en diagonal ascendente completando el resto con ceros" + ] + }, + { + "cell_type": "code", + "execution_count": 58, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[4, 0, 0, 0],\n", + " [0, 3, 0, 0],\n", + " [0, 0, 2, 0],\n", + " [0, 0, 0, 1]])" + ] + }, + "execution_count": 58, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a = np.diag([1,2,3,4])\n", + "np.rot90(a, k=2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, "source": [ - "B = A.reshape(A.shape) # es igual a A.copy()" + "Podemos decirle qué diagonal con un offset entero" ] }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 59, "metadata": { "collapsed": false }, @@ -151,16 +1649,19 @@ { "data": { "text/plain": [ - "False" + "array([[0, 1, 0, 0],\n", + " [0, 0, 2, 0],\n", + " [0, 0, 0, 3],\n", + " [0, 0, 0, 0]])" ] }, - "execution_count": 13, + "execution_count": 59, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "A is B" + "np.diag([1,2,3], k=1)" ] }, { @@ -172,7 +1673,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 63, "metadata": { "collapsed": false }, @@ -185,7 +1686,7 @@ " [6, 7, 8]])" ] }, - "execution_count": 14, + "execution_count": 63, "metadata": {}, "output_type": "execute_result" } @@ -196,7 +1697,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 64, "metadata": { "collapsed": false }, @@ -209,7 +1710,7 @@ " [0, 3, 6]])" ] }, - "execution_count": 15, + "execution_count": 64, "metadata": {}, "output_type": "execute_result" } @@ -220,7 +1721,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 65, "metadata": { "collapsed": false }, @@ -233,7 +1734,7 @@ " [2, 1, 0]])" ] }, - "execution_count": 16, + "execution_count": 65, "metadata": {}, "output_type": "execute_result" } @@ -246,29 +1747,28 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Meshgrids \n", - "\n", - "Una funcion importante es `meshgrid`, que permite " + "### Meshgrids" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Una funcion importante es `meshgrid`, que permite" ] }, { "cell_type": "code", - "execution_count": 90, + "execution_count": 66, "metadata": { "collapsed": false }, "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[-3. -2. -1. 0. 1. 2. 3.]\n", - "[-3. -2. -1. 0. 1. 2.]\n" - ] - }, { "data": { "text/plain": [ + "[-3. -2. -1. 0. 1. 2. 3.]\n", + "[-3. -2. -1. 0. 1. 2.]\n", "[array([[-3., -2., -1., 0., 1., 2., 3.],\n", " [-3., -2., -1., 0., 1., 2., 3.],\n", " [-3., -2., -1., 0., 1., 2., 3.],\n", @@ -283,7 +1783,7 @@ " [ 2., 2., 2., 2., 2., 2., 2.]])]" ] }, - "execution_count": 90, + "execution_count": 66, "metadata": {}, "output_type": "execute_result" } @@ -306,9 +1806,9 @@ }, { "cell_type": "code", - "execution_count": 58, + "execution_count": 67, "metadata": { - "collapsed": false + "collapsed": true }, "outputs": [], "source": [ @@ -318,7 +1818,7 @@ }, { "cell_type": "code", - "execution_count": 73, + "execution_count": 68, "metadata": { "collapsed": false }, @@ -334,7 +1834,7 @@ " [-12., -8., -4., 0., 4., 8., 12.]])" ] }, - "execution_count": 73, + "execution_count": 68, "metadata": {}, "output_type": "execute_result" } @@ -346,32 +1846,11 @@ }, { "cell_type": "code", - "execution_count": 74, + "execution_count": 69, "metadata": { - "collapsed": false + "collapsed": true }, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 74, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\nIskYb6mHAZeIOIAKZY63FBBwM/sbMztuZsfM7CEz2xnzYKsM4ueo9DziTOHlMX1XIPDnmYQImcD/\nzt13u/vFku6V9NeRztRK6YhvvlD2/qltPlr6BOk8sfmD0kdI6+hm6ROs1gR870ubkQ4RoFC4pzoH\n3N3/d+bTsyX9T/hxuikZ8c0XAx+g8il887HlX+/zFP5kzwO+cvo+tpnlHJ01gd//w80IhwhQON5S\n4A7czP7WzP5L0p9IujXOkbopPYkHqTziQHRN6QMEqiDe0oqAm9khM3tizn/+SJLcfa+7v1HSP0n6\n+wznXYqIAz3QlD5AgIL77nnM3cMfxOyNkh5w9wvnfC38BgAwQu5uy77e+Z2YZrbL3Z+dfHqtpKNd\nDgAA6KbzBG5md0l6s6SfS/pPSR9w99Cn9AAAa4qyQgEA5JflnZil3/STkpndbmYnJn++e8zsnNJn\nisnM3m1mT5nZz83st0qfJxYzu8rMnjGzZ81sUD9izMw+a2YvmNkTpc+SgpntNLPDk/9dPmlmHyx9\npljM7BfM7MiklU+b2ceXXp9jAjezX56+btzM/lLSbnf/0+Q3zsDMrpD0kLu/Yma3SpK731z4WNGY\n2QWSXpG0T9KH3f0bhY8UzMzOlPQtSb8v6XlJj0ra4+4nih4sEjP7HUkvS/q8u19U+jyxmdkOSTvc\n/ZiZnS3pcUnvGNDf3y+5+4/N7CxJj0j6iLs/Mu/aLBN4TW/6ic3dD7n7K5NPj0j69ZLnic3dn3H3\n/yh9jsjeJuk5d/+2u/9M0he19UT8ILj71yS9VPocqbj799z92OTjlyWdkPT6sqeKx91/PPnwtZLO\nlLTwHWfZfphVTW/6Sej9kh4ofQis9AZJ35n5/LuTf4aeMbPzJV2ireFpEMzsDDM7JukFSYfd/elF\n10b7hQ5mdkjSjjlfusXd73f3vZL2mtnN2nrTz/ti3Tu1VX+2yTV7Jf3U3e/MergI1vnzDQzP3A/A\nZH1yl6QPTSbxQZj8G/3Fk+fTvmpmG+6+Oe/aaAF39yvWvPRO9WxKXfVnM7P3SvoDSZdnOVBkLf7u\nhuJ5SbNPpO/U1hSOnjCz10i6W9IX3P3e0udJwd1/ZGZflnSppM151+R6FcqumU8Xvumnj8zsKkk3\nSrrW3X9S+jyJDeVNWY9J2mVm55vZayW9R9J9hc+ENZmZSfqMpKfd/ROlzxOTmZ1nZr8y+fgXJV2h\nJb3M9SqUwb7px8ye1daTDdMnGv7N3f+84JGiMrN3SvqkpPMk/UjSUXe/uuypwpnZ1ZI+oa0niT7j\n7ktfrtUnZnZA0mWSXifpRUkfc/f9ZU8Vj5n9tqSHJX1TJ9dhH3X3r5Q7VRxmdpGkz2lruD5D0j+7\n++0Lr+eNPADQT738lWoAAAIOAL1FwAGgpwg4APQUAQeAniLgANBTBBwAeoqAA0BP/T/bgi/yzkPE\nLwAAAABJRU5ErkJggg==\n", - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "plt.contourf(x, y, z)" ] @@ -392,7 +1871,7 @@ }, { "cell_type": "code", - "execution_count": 96, + "execution_count": 70, "metadata": { "collapsed": false }, @@ -403,7 +1882,7 @@ "array([ 1, 15, 30, 5, 7, 29, 5, 8, 25, 30])" ] }, - "execution_count": 96, + "execution_count": 70, "metadata": {}, "output_type": "execute_result" } @@ -415,7 +1894,7 @@ }, { "cell_type": "code", - "execution_count": 92, + "execution_count": 71, "metadata": { "collapsed": false }, @@ -426,7 +1905,7 @@ "array([28, 29, 17, 28])" ] }, - "execution_count": 92, + "execution_count": 71, "metadata": {}, "output_type": "execute_result" } @@ -444,7 +1923,7 @@ }, { "cell_type": "code", - "execution_count": 97, + "execution_count": 72, "metadata": { "collapsed": false }, @@ -455,7 +1934,7 @@ "array([False, False, True, False, False, True, False, False, True, True], dtype=bool)" ] }, - "execution_count": 97, + "execution_count": 72, "metadata": {}, "output_type": "execute_result" } @@ -473,7 +1952,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 73, "metadata": { "collapsed": false }, @@ -484,7 +1963,7 @@ "array([23, 20, 15, 30, 18, 12, 21, 18, 18])" ] }, - "execution_count": 21, + "execution_count": 73, "metadata": {}, "output_type": "execute_result" } @@ -497,15 +1976,20 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "(Este tipo de slicing especial **crea copias**, no vistas. Usar cuando lo amerite.)\n", - "\n", + "(Este tipo de slicing especial **crea copias**, no vistas. Usar cuando lo amerite.)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ "\n", "Si en vez de los valores que cumples una condición, queremos las posiciones, podemos usar la función `where`" ] }, { "cell_type": "code", - "execution_count": 98, + "execution_count": 74, "metadata": { "collapsed": false }, @@ -516,18 +2000,18 @@ "(array([2, 5, 8, 9]),)" ] }, - "execution_count": 98, + "execution_count": 74, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "np.where(a > 15) # devuelve las posiciones. " + "np.where(a > 15) # devuelve las posiciones." ] }, { "cell_type": "code", - "execution_count": 100, + "execution_count": 75, "metadata": { "collapsed": false }, @@ -538,7 +2022,7 @@ "array([ 0, 0, 30, 0, 0, 29, 0, 0, 25, 30])" ] }, - "execution_count": 100, + "execution_count": 75, "metadata": {}, "output_type": "execute_result" } @@ -549,7 +2033,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 76, "metadata": { "collapsed": false }, @@ -560,38 +2044,47 @@ "array([23, 20, 15, 0, 30, 18, 12, 21, 18, 18])" ] }, - "execution_count": 24, + "execution_count": 76, "metadata": {}, "output_type": "execute_result" } ], "source": [ "b = 0\n", - "np.where(a > 10, a, b) # para cada i-elemento a[i] si True, si no b[i] (o constante) " + "np.where(a > 10, a, b) # para cada i-elemento a[i] si True, si no b[i] (o constante)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Selecciones avanzadas: \n", - "\n", - "![](http://scipy-lectures.github.io/_images/numpy_fancy_indexing.png)\n", - "\n" + "Selecciones avanzadas:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Lectura desde texto y archivos\n", - "\n", - "Como numpy se especializa en manejar números, tiene muchas funciones para crear arrays a partir de información numérica a partir de texto o archivos (como los CSV, por ejemplo).\n" + "![](http://scipy-lectures.github.io/_images/numpy_fancy_indexing.png)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Lectura desde texto y archivos" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Como numpy se especializa en manejar números, tiene muchas funciones para crear arrays a partir de información numérica a partir de texto o archivos (como los CSV, por ejemplo)." ] }, { "cell_type": "code", - "execution_count": 107, + "execution_count": 77, "metadata": { "collapsed": false }, @@ -603,13 +2096,13 @@ " [-3.1, 2. , 5. , 4.5]])" ] }, - "execution_count": 107, + "execution_count": 77, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "a_desde_str = np.fromstring(u\"\"\"1.0 2.3 3.0 4.1 \n", + "a_desde_str = np.fromstring(u\"\"\"1.0 2.3 3.0 4.1\n", "-3.1 2 5.0 4.5\"\"\", sep=\" \", dtype=float)\n", "a_desde_str.shape = (2, 4)\n", "a_desde_str" @@ -624,9 +2117,9 @@ }, { "cell_type": "code", - "execution_count": 112, + "execution_count": 78, "metadata": { - "collapsed": false + "collapsed": true }, "outputs": [], "source": [ @@ -635,9 +2128,9 @@ }, { "cell_type": "code", - "execution_count": 108, + "execution_count": 79, "metadata": { - "collapsed": false + "collapsed": true }, "outputs": [], "source": [ @@ -653,7 +2146,7 @@ }, { "cell_type": "code", - "execution_count": 113, + "execution_count": 80, "metadata": { "collapsed": false }, @@ -664,7 +2157,7 @@ "(211, 4)" ] }, - "execution_count": 113, + "execution_count": 80, "metadata": {}, "output_type": "execute_result" } @@ -683,7 +2176,7 @@ }, { "cell_type": "code", - "execution_count": 114, + "execution_count": 81, "metadata": { "collapsed": false }, @@ -729,7 +2222,7 @@ " 190.564 ])" ] }, - "execution_count": 114, + "execution_count": 81, "metadata": {}, "output_type": "execute_result" } @@ -747,187 +2240,18 @@ }, { "cell_type": "code", - "execution_count": 115, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "t, p, d, x = np.loadtxt('data/critical.dat', skiprows=2, usecols=[0, 1, 2, 3], unpack=True)" - ] - }, - { - "cell_type": "code", - "execution_count": 116, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "data": { - "text/plain": [ - "array([ 304.21 , 304.2056, 304.2011, 304.192 , 304.174 , 304.1379,\n", - " 304.0657, 303.9211, 303.6309, 303.2894, 302.9461, 302.6013,\n", - " 302.2547, 301.9064, 301.5565, 301.2048, 300.8514, 300.4962,\n", - " 300.1394, 299.7807, 299.4203, 299.0581, 298.6941, 298.3283,\n", - " 297.9606, 297.5911, 297.2198, 296.8466, 296.4716, 296.0946,\n", - " 295.7158, 295.335 , 294.9524, 294.5677, 294.1812, 293.7927,\n", - " 293.4022, 293.0097, 292.6152, 292.2187, 291.8201, 291.4195,\n", - " 291.0169, 290.6122, 290.2054, 289.7965, 289.3855, 288.9724,\n", - " 288.5572, 288.1398, 287.7202, 287.2984, 286.8745, 286.4484,\n", - " 286.02 , 285.5894, 285.1566, 284.7215, 284.2841, 283.8444,\n", - " 283.4025, 282.9582, 282.5116, 282.0627, 281.6114, 281.1577,\n", - " 280.7017, 280.2432, 279.7824, 279.3192, 278.8535, 278.3854,\n", - " 277.9148, 277.4417, 276.9662, 276.4882, 276.0077, 275.5246,\n", - " 275.0391, 274.551 , 274.0603, 273.5671, 273.0714, 272.573 ,\n", - " 272.0721, 271.5686, 271.0625, 270.5537, 270.0424, 269.5284,\n", - " 269.0117, 268.4925, 267.9705, 267.446 , 266.9187, 266.3888,\n", - " 265.8562, 265.321 , 264.7831, 264.2425, 263.6992, 263.1532,\n", - " 262.6045, 262.0532, 261.4991, 260.9424, 260.383 , 259.821 ,\n", - " 259.2562, 258.6888, 258.1187, 257.546 , 256.9706, 256.3925,\n", - " 255.8118, 255.2285, 254.6426, 254.0541, 253.4629, 252.8692,\n", - " 252.2729, 251.6741, 251.0727, 250.4688, 249.8625, 249.2536,\n", - " 248.6422, 248.0284, 247.4122, 246.7935, 246.1725, 245.5491,\n", - " 244.9234, 244.2953, 243.665 , 243.0323, 242.3974, 241.7603,\n", - " 241.121 , 240.4795, 239.8358, 239.19 , 238.542 , 237.892 ,\n", - " 237.2398, 236.5856, 235.9294, 235.2711, 234.6108, 233.9484,\n", - " 233.2841, 232.6178, 231.9494, 231.2791, 230.6067, 229.9324,\n", - " 229.256 , 228.5776, 227.8971, 227.2145, 226.5299, 225.843 ,\n", - " 225.154 , 224.4628, 223.7692, 223.0734, 222.3751, 221.6743,\n", - " 220.971 , 220.265 , 219.5564, 218.8448, 218.1304, 217.4129,\n", - " 216.6923, 215.9683, 215.2409, 214.51 , 213.7753, 213.0367,\n", - " 212.2941, 211.5473, 210.7961, 210.0403, 209.2797, 208.5141,\n", - " 207.7433, 206.967 , 206.1851, 205.3974, 204.6034, 203.8032,\n", - " 202.9963, 202.1825, 201.3615, 200.5331, 199.697 , 198.8528,\n", - " 198.0004, 197.1393, 196.2693, 195.3901, 194.5014, 193.6027,\n", - " 192.6939, 191.7744, 190.8441, 190.7051, 190.6356, 190.6008,\n", - " 190.564 ])" - ] - }, - "execution_count": 116, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "t" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "data": { - "text/plain": [ - "211" - ] - }, - "execution_count": 23, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "t.size" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Podemos graficar algo sencillo" - ] - }, - { - "cell_type": "code", - "execution_count": 117, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "%matplotlib inline" - ] - }, - { - "cell_type": "code", - "execution_count": 118, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "from matplotlib import pyplot\n", - "pyplot.plot(t, p, 'r') # el tercer parámetro es el formato\n", - "pyplot.title('Critical pressure vs temperature')\n", - "pyplot.grid()\n", - "pyplot.xlabel('Temperature [K]')\n", - "pyplot.ylabel('Pressure [bar]')\n", - "# el punto y coma evita el output\n", - "pyplot.show();" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Arrays con columnas de distinto tipo\n", - "\n", - "Para leer archivos con estructuras más complejas (o con datos faltantes) existe `numpy.genfromtxt()`. Pero además, esta función soporta un parámetro `names` para convertir el output en un **array estructurado** (o *record array*), que es parecido a un diccionario o una \"hoja de cálculo\", donde la homogeneidad es por columna y se puede acceder por una clave.\n", - "\n", - "Esto no usa tanto desde que apareció el paquete [Pandas](http://pandas.pydata.org/)\n" - ] - }, - { - "cell_type": "code", - "execution_count": 122, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "data": { - "text/plain": [ - "dtype([('T', '');\n", - " this._root_extra_style(this.root)\n", - " this.root.attr('style', 'display: inline-block');\n", - "\n", - " $(parent_element).append(this.root);\n", - "\n", - " this._init_header(this);\n", - " this._init_canvas(this);\n", - " this._init_toolbar(this);\n", - "\n", - " var fig = this;\n", - "\n", - " this.waiting = false;\n", - "\n", - " this.ws.onopen = function () {\n", - " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", - " fig.send_message(\"send_image_mode\", {});\n", - " fig.send_message(\"refresh\", {});\n", - " }\n", - "\n", - " this.imageObj.onload = function() {\n", - " if (fig.image_mode == 'full') {\n", - " // Full images could contain transparency (where diff images\n", - " // almost always do), so we need to clear the canvas so that\n", - " // there is no ghosting.\n", - " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", - " }\n", - " fig.context.drawImage(fig.imageObj, 0, 0);\n", - " fig.waiting = false;\n", - " };\n", - "\n", - " this.imageObj.onunload = function() {\n", - " this.ws.close();\n", - " }\n", - "\n", - " this.ws.onmessage = this._make_on_message_function(this);\n", - "\n", - " this.ondownload = ondownload;\n", - "}\n", - "\n", - "mpl.figure.prototype._init_header = function() {\n", - " var titlebar = $(\n", - " '
');\n", - " var titletext = $(\n", - " '
');\n", - " titlebar.append(titletext)\n", - " this.root.append(titlebar);\n", - " this.header = titletext[0];\n", - "}\n", - "\n", - "\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "\n", - "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "mpl.figure.prototype._init_canvas = function() {\n", - " var fig = this;\n", - "\n", - " var canvas_div = $('
');\n", - "\n", - " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", - "\n", - " function canvas_keyboard_event(event) {\n", - " return fig.key_event(event, event['data']);\n", - " }\n", - "\n", - " canvas_div.keydown('key_press', canvas_keyboard_event);\n", - " canvas_div.keyup('key_release', canvas_keyboard_event);\n", - " this.canvas_div = canvas_div\n", - " this._canvas_extra_style(canvas_div)\n", - " this.root.append(canvas_div);\n", - "\n", - " var canvas = $('');\n", - " canvas.addClass('mpl-canvas');\n", - " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", - "\n", - " this.canvas = canvas[0];\n", - " this.context = canvas[0].getContext(\"2d\");\n", - "\n", - " var rubberband = $('');\n", - " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", - "\n", - " var pass_mouse_events = true;\n", - "\n", - " canvas_div.resizable({\n", - " start: function(event, ui) {\n", - " pass_mouse_events = false;\n", - " },\n", - " resize: function(event, ui) {\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " stop: function(event, ui) {\n", - " pass_mouse_events = true;\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " });\n", - "\n", - " function mouse_event_fn(event) {\n", - " if (pass_mouse_events)\n", - " return fig.mouse_event(event, event['data']);\n", - " }\n", - "\n", - " rubberband.mousedown('button_press', mouse_event_fn);\n", - " rubberband.mouseup('button_release', mouse_event_fn);\n", - " // Throttle sequential mouse events to 1 every 20ms.\n", - " rubberband.mousemove('motion_notify', mouse_event_fn);\n", - "\n", - " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", - " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", - "\n", - " canvas_div.on(\"wheel\", function (event) {\n", - " event = event.originalEvent;\n", - " event['data'] = 'scroll'\n", - " if (event.deltaY < 0) {\n", - " event.step = 1;\n", - " } else {\n", - " event.step = -1;\n", - " }\n", - " mouse_event_fn(event);\n", - " });\n", - "\n", - " canvas_div.append(canvas);\n", - " canvas_div.append(rubberband);\n", - "\n", - " this.rubberband = rubberband;\n", - " this.rubberband_canvas = rubberband[0];\n", - " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", - " this.rubberband_context.strokeStyle = \"#000000\";\n", - "\n", - " this._resize_canvas = function(width, height) {\n", - " // Keep the size of the canvas, canvas container, and rubber band\n", - " // canvas in synch.\n", - " canvas_div.css('width', width)\n", - " canvas_div.css('height', height)\n", - "\n", - " canvas.attr('width', width);\n", - " canvas.attr('height', height);\n", - "\n", - " rubberband.attr('width', width);\n", - " rubberband.attr('height', height);\n", - " }\n", - "\n", - " // Set the figure to an initial 600x600px, this will subsequently be updated\n", - " // upon first draw.\n", - " this._resize_canvas(600, 600);\n", - "\n", - " // Disable right mouse context menu.\n", - " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", - " return false;\n", - " });\n", - "\n", - " function set_focus () {\n", - " canvas.focus();\n", - " canvas_div.focus();\n", - " }\n", - "\n", - " window.setTimeout(set_focus, 100);\n", - "}\n", - "\n", - "mpl.figure.prototype._init_toolbar = function() {\n", - " var fig = this;\n", - "\n", - " var nav_element = $('
')\n", - " nav_element.attr('style', 'width: 100%');\n", - " this.root.append(nav_element);\n", - "\n", - " // Define a callback function for later on.\n", - " function toolbar_event(event) {\n", - " return fig.toolbar_button_onclick(event['data']);\n", - " }\n", - " function toolbar_mouse_event(event) {\n", - " return fig.toolbar_button_onmouseover(event['data']);\n", - " }\n", - "\n", - " for(var toolbar_ind in mpl.toolbar_items) {\n", - " var name = mpl.toolbar_items[toolbar_ind][0];\n", - " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", - " var image = mpl.toolbar_items[toolbar_ind][2];\n", - " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", - "\n", - " if (!name) {\n", - " // put a spacer in here.\n", - " continue;\n", - " }\n", - " var button = $('