diff --git a/LEEME.md b/LEEME.md new file mode 100644 index 0000000..c1760ba --- /dev/null +++ b/LEEME.md @@ -0,0 +1,52 @@ +# Cálculos Computacionales en Ingeniería - Módulo 1 + +_Cálculos Computacionales en Ingeniería_ es un curso en línea realizado con módulos de aprendizaje intercambiables, proporcionando flexibilidad para adaptarlo a diversas situaciones. Apunta a desarrollar habilidades computacionales para estudiantes en ingeniería, pero también puede ser usado por estudiantes de otras disciplinas científicas. El curso utiliza el lenguaje de programación Python y las herramientas de código abierto de Jupyter para computación interactiva. + +Este primer módulo no asume ninguna experiencia previa en programación, por lo que las tres primeras lecciones se centran en crear una base de conocimientos de programación en Python sin hacer uso de Matemáticas. La cuarta lección introduce la estructura de datos básicos en la informática científica: _arrays_. La última lección es un ejemplo de regresión lineal con datos reales. + +## Sobre la traducción + +La traducción de los módulos escritos originalmente en inglés se realiza de manera literal, tratando de mantener un español neutro y fácil de leer. Se traducirá los nombres de archivos de notebook, comentarios, mensajes, valores de los strings, y de manera general, lo que ayude a hacer más facil de entender el código. Sin embargo, no se traducirán los nombres de variables ni el contenido de los datos de ejemplo. Es necesario de todas maneras aprender un poco de inglés para comprender y redactar de mejor manera código de Python, por lo que el código en sí mismo se mantendrá casi completamente en inglés. + +## Módulo 1: Obtener datos + +_Aprender a interactuar con Python y manejar datos en Python._ + +> Obten una sesión interactiva en [MyBinder.org](https://mybinder.org/) con el material del curso utilizando el botón inferior. +> Selecciona la carpeta `notebooks_es` para acceder a las 5 lecciones de este curso como notebooks de Jupyter completamente ejecutables. +> +> [![Binder](https://mybinder.org/badge.svg)](https://mybinder.org/v2/gh/engineersCode/EngComp1_offtheground/master) + +* **Puedes unirte al curso [open online course](https://openedx.seas.gwu.edu/courses/course-v1:GW+EngComp1+2018/about)** (en inglés) en nuestra plataforma _Open edX_. + +* **Obtener una versión PDF para imprimir** (en inglés): _Engineering Computations Module 1: Get data off the ground._ figshare. https://doi.org/10.6084/m9.figshare.5673454.v1 + +### [Lección 1](https://github.com/engineersCode/EngComp1_offtheground/blob/translation_es/notebooks_es/1_Interactuando_con_Python.ipynb): Interactuando con Python. + +Antecedentes: ¿Qué es Python? Nociones de lenguaje interpretado en comparación a lenguaje compilado. ¿Por qué usar Python? Es un lenguaje de uso general y de alta productividad. +Primeros pasos: Python interactivo (IPython). +Utilizando Python como una calculadora. +Nuevos conceptos: funciones, strings, variables, asignación, tipo, variables especiales (`True`,` False`, `None`). +Operaciones matemáticas, operaciones lógicas. Lectura de mensajes de error. + +### [Lección 2](https://github.com/engineersCode/EngComp1_offtheground/blob/translation_es/notebooks_es/2_Strings_y_listas_en_Jupyter.ipynb): Jugando con los datos en Jupyter + +¿Qué es Jupyter? Trabajando con Jupyter. Jugando con cadenas de texto (strings) en Python: asignación, indexación, subdivisión. Métodos de cadenas de texto: count, find, index, strip, startswith, split. Jugando con listas de Python: asignación, listas anidadas, indexación, segmentación. Métodos de listas: agregar, indexar. Pertenencia a una lista. Iteración con declaraciones for. Condicionales. + +### [Lección 3](https://github.com/engineersCode/EngComp1_offtheground/blob/translation_es/notebooks_es/3_Ejemplo_con_MAEbulletin.ipynb): Cadenas de texto y listas en acción + +Un ejemplo completo que utiliza lo aprendido en las lecciones 1 y 2: jugando con un archivo de texto que contiene el boletín MAE (lista de cursos con sus números, descripción, requisitos previos). Lectura de datos de un archivo. Limpieza y organización de datos de un texto. + +### [Lección 4](https://github.com/engineersCode/EngComp1_offtheground/blob/translation_es/notebooks_es/4_NumPy_Arrays_y_Graficos.ipynb): Jugando con matrices NumPy + +Dos de las bibliotecas más importantes para informática científica con Python: **NumPy** y **Matplotlib**. Importando bibliotecas. Funciones de NumPy para crear matrices: linspace, ones, zeros, empty, copy. Operaciones de un array. Matrices multidimensionales. Ventaja de rendimiento de arrays sobre listas. Graficando líneas 2D de datos a partir de arrays. + +### [Lección 5](https://github.com/engineersCode/EngComp1_offtheground/blob/translation_es/notebooks_es/5_Regresion_Lineal_con_datos_reales.ipynb): Regresión lineal con datos reales + +Un ejemplo completo que usa datos reales de la temperatura de la tierra a lo largo del tiempo. Paso 1: leer datos de un archivo. Paso 2: graficar los datos; haciendo gráficos hermosos. Paso 3: regresión lineal de mínimos cuadrados. Paso 4: aplicar regresión lineal usando NumPy. Bonus: regresión segmentada. + +## Derechos de autor y licencia + +(c) 2017 Lorena A. Barba, Natalia C. Clementi. Todo el contenido está bajo Atribución de Creative Commons [CC-BY 4.0](https://creativecommons.org/licenses/by/4.0/legalcode.txt), y todo [el código está bajo la cláusula BSD-3](https://github.com/engineersCode/EngComp/blob/master/LICENCE). ¡Estaremos felices si reutilizas el contenido de alguna manera! + +[![Licencia](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause) [![Licencia: CC BY 4.0](https://img.shields.io/badge/License-CC%20BY%204.0-lightgrey.svg)](https://creativecommons.org/licenses/by/4.0/) [![Licencia: CC BY 4.0](https://img.shields.io/badge/Original-English-lightgreen.svg)](https://github.com/engineersCode/EngComp1_offtheground/) diff --git a/notebooks_en/1_Interacting_with_Python.ipynb b/notebooks_en/1_Interacting_with_Python.ipynb index dfe30e5..47ae4d8 100644 --- a/notebooks_en/1_Interacting_with_Python.ipynb +++ b/notebooks_en/1_Interacting_with_Python.ipynb @@ -1437,7 +1437,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.5.3" + "version": "3.6.4" }, "widgets": { "state": {}, diff --git a/notebooks_es/1_Interactuando_con_Python.ipynb b/notebooks_es/1_Interactuando_con_Python.ipynb new file mode 100644 index 0000000..0a7509f --- /dev/null +++ b/notebooks_es/1_Interactuando_con_Python.ipynb @@ -0,0 +1,1050 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "###### Contenido bajo licencia Creative Commons Attribution CC-BY 4.0, código bajo licencia BSD 3-Clause © 2017 L.A. Barba, N.C. Clementi" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Interactuando con Python\n", + "\n", + "Esta es la primera lección de nuestro curso _\"Cálculos Computacionales en Ingeniería\"_, un curso de un semestre para estudiantes universitarios de segundo año. El curso usa Python y no asume experiencia previa en programación.\n", + "Nuestro primer paso será interactuar con Python. Pero primero aprenderemos algunos datos interesantes." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## ¿Qué es Python?\n", + "\n", + "Python tiene más de 25 años de existencia, puesto que su primera versión se liberó en 1991. Su creador, [Guido van Rossum](https://es.wikipedia.org/wiki/Guido_van_Rossum), lo nombró así por la comedia británica \"Monty Python Flying Circus\". Sus objetivos para el lenguaje eran que era un \"lenguaje fácil e intuitivo, tan poderoso como los principales competidores\", produciendo un código de computadora \"que sea tan comprensible como el inglés\".\n", + "\n", + "Es un lenguaje de propósito general, lo que significa que puede ser usardo para cualquier objetivo: organización de datos, web scraping, creación de sitios web, análisis de sonidos, creación de juegos y, por supuesto, *cálculos computacionales en ingeniería*.\n", + "\n", + "Python es un lenguaje interpretado. Esto significa que puedes escribir comandos de Python y la computadora ejecuta esas instrucciones directamente. Otros lenguajes de programación, como C, C ++ y Fortran, requieren un paso previo de _compilación_: traducir los comandos al lenguaje de la máquina.\n", + "Una gran habilidad de Python es que puede ser utilizada _interactivamente_. Fernando Perez creó ** IPython ** como un proyecto paralelo durante su doctorado. Vamos a usar IPython (el I significa \"interactivo\") en esta lección." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## ¿Por qué Python?\n", + "\n", + "\n", + "_¡Porque es divertido!_ Con Python, cuanto más aprendes, más te gustará aprender.\n", + "Existen muchos recursos en línea y, dado que Python es un proyecto de código abierto, también encontrarás una comunidad amigable de personas que comparten sus conocimientos.\n", + "\n", + "Python es conocido como un lenguaje de \"alta productividad\". Como programador, necesitarás menos tiempo para desarrollar una solución con Python que con la mayoría de los idiomas.\n", + "Esto es importante cuando alguien te diga que \"Python es lento\".\n", + "¡Tu tiempo es más valioso que el de una máquina!\n", + "(Al respecto, consulta la sección Lecturas recomendadas al final de este notebook).\n", + "Y si realmente necesitamos acelerar nuestro programa, podemos volver a escribir las partes lentas en un lenguaje compilado más tarde, porque Python interactua bien con otros idiomas :-)\n", + "\n", + "Las principales compañías tecnológicas usan Python: Google, Facebook, Dropbox, Wikipedia, Yahoo!, YouTube ... Y el 2017, Python ocupó el lugar número 1 en la lista interactiva de [The 2017 Top Programming Languages](http://spectrum.ieee.org/computing/software/the-2017-top-programming-languages), por _EEEE Spectrum_ ([IEEE](http://www.ieee.org/about/index.html) es la sociedad técnica profesional más grande del mundo )" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### _Python es un lenguaje versátil, puede analizar datos, crear sitios web (por ejemplo, Instagram, Mozilla, Pinterest), hacer arte o música, etc. Debido a que es un lenguaje versátil, los empleadores adoran Python: si conoces Python, querrán contratarte._ —Jessica McKellar, ex Directora de la Python Software Foundation, en un [tutorial de 2014](https://youtu.be/rkx5_MRAV3A)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Empecemos\n", + "\n", + "En esta primera lección, usaremos IPython: una herramienta para trabajar con Python de forma interactiva. Si ya lo tienes instalado en la computadora que estás utilizando para esta lección, ingresa al programa escribiendo\n", + "\n", + "`ipython`\n", + "\n", + "en la interfaz de la línea de comandos (la aplicación **Terminal** en Mac OSX, y en Windows posiblemente la **PowerShell** o **git bash**). Obtendrás algunas líneas de texto sobre tu versión de IPython y cómo obtener ayuda, y un cursor parpadeante al lado del contador de línea de entrada:\n", + "\n", + "`En [1]:`\n", + "\n", + "Esa línea de entrada está lista para recibir cualquier código de Python para ser ejecutado de manera interactiva. La salida del código se mostrará junto a `Out [1]`, y así sucesivamente para líneas sucesivas de entrada/salida.\n", + "\n", + "##### Nota:\n", + "\n", + "Nuestro plan para este curso es trabajar en un laboratorio de computación, donde todos tendrán una computadora con todo instalado con anticipación. Por esta razón, no discutiremos la instalación en este momento. Más adelante, cuando estés ansioso por trabajar en su computadora personal, te ayudaremos a instalar todo lo que necesita. _¡Sí, es gratis!_" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Tu primer programa\n", + "\n", + "En todo curso de programación, tu primer programa consiste en imprimir un mensaje que diga _\"Hola mundo\"_. En Python, esto se logra con la función `print()`, con su mensaje entre comillas." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(\"¡Hola mundo!\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "¡¡Pan comido!! acabas de escribir tu primer programa y aprendiste a usar la función `print()`. Sí, `print()` es una función: pasamos el _argumento_ sobre el que queremos que actúe la función, dentro de los paréntesis. En el caso anterior, pasamos un _string_ o _cadena de texto_, que es una serie de caracteres entre comillas. No te preocupes, volveremos a los strings más adelante en esta lección." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##### Concepto clave: función\n", + "\n", + "Una función es una colección compacta de código que ejecuta alguna acción en sus _argumentos_. Cada función de Python tiene un _nombre_, usado para llamarlo, y toma sus argumentos dentro de paréntesis. Algunos argumentos pueden ser opcionales (lo que significa que tienen un valor predeterminado definido dentro de la función), otros son obligatorios. Por ejemplo, la función `print()` tiene un argumento requerido: la cadena de caracteres que se desea imprimir.\n", + "\n", + "Python viene con muchas funciones _predefinidas_, pero también puedes construir funciones propias. Dividir los distintos bloques de código en funciones es una de las mejores estrategias para lidiar con programas complejos. Te hace más eficiente, porque puedes reutilizar el código que escribiste en una función. La modularidad y la reutilización son las herramientas diarias de un programador." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Python como calculadora\n", + "\n", + "Prueba cualquier operación aritmética en IPython. Los símbolos son lo que esperaría, excepto el operador de potencia, que se obtiene con dos asteriscos: `**`. Prueba todos estos operadores:\n", + "\n", + "```python\n", + "+ - * / ** % //\n", + "```\n", + "\n", + "El símbolo `%` es el operador _módulo_ (divide y devuelve el resto), y la barra doble `//` es _división entera_." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "2 + 2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "1.25 + 3.65" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "5 - 3" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "2 * 4" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "7 / 2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "2**3" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Veamos un caso interesante:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "9**1/2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##### Discute con tu vecino:\n", + "_¿Qué pasó?_¿No es $ 9 ^ {1/2} = 3 $? (Aumentar al poder $ 1/2 $ es lo mismo que tomar la raíz cuadrada.) ¿Python se equivocó?\n", + "\n", + "Compara con esto:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "9**(1/2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "¡Sí! ¡El orden de las operaciones es importante!\n", + "\n", + "Si no recuerdas de lo que estamos hablando, revisa la [Aritmética/Orden de operaciones](https://es.wikipedia.org/wiki/Orden_de_evaluaci%C3%B3n). Una situación frecuente que expone esto es la siguiente:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "3 + 3 / 2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "(3 + 3) / 2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "En el primer caso, estamos agregando $ 3 $ más el número resultante de la operación $ 3/2 $. Si queremos que la división se aplique al resultado de $ 3 + 3 $, necesitamos los paréntesis." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##### Ejercicios:\n", + "Usa IPython (como una calculadora) para resolver los siguientes dos problemas:\n", + "\n", + "1. El volumen de una esfera con radio $ r $ es $ \\frac {4} {3} \\pi r ^ 3 $. ¿Cuál es el volumen de una esfera con un diámetro de 6.65 cm? Utiliza 3.14159 como valor para $ \\pi $ (por ahora). Compara tu respuesta con la solución hasta 4 números decimales.\n", + "\n", + "    Sugerencia: 523.5983 es incorrecto y 615.9184 también es incorrecto.\n", + "\n", + "\n", + "2. Supongamos que el precio de un libro es $ \\$ 24.95 $, pero las librerías obtienen un descuento de $ 40 \\% $. El envío cuesta $ \\$ 3 $ por la primera copia y $ 75 $ centavos por cada copia adicional. ¿Cuál es el costo total al por mayor de $ 60 $ copias? Compare su respuesta con la solución hasta 2 números decimales." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Para revelar las respuestas, resalta la siguiente línea de texto con el ratón:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Respuesta ejercicio 1: 153.9796 \n", + "\n", + "Respuesta ejercicio 2: 945.45 " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Variables y su tipo\n", + "\n", + "Las variables constan de dos partes: un nombre (_name_) y un valor (_value_). Cuando queremos dar a una variable su nombre y valor, usamos el signo igual: `nombre = valor`. Esto se llama una 'asignación'. El nombre de la variable va a la izquierda y el valor a la derecha.\n", + "\n", + "¡Lo primero a lo que hay que acostumbrarse es a que el signo igual en una tarea tiene un significado diferente del que tiene en Algebra! Imagina que es una flecha que apunta del `nombre` al ` valor`.\n", + "\n", + "\n", + "\n", + "Tenemos muchas posibilidades para los nombres de variables: pueden estar formados por letras mayúsculas y minúsculas, guiones bajos y dígitos, pero los dígitos no pueden ir al principio del nombre. Por ejemplo, algunos nombres de variable válidos son:\n", + "\n", + "```python\n", + "    X\n", + "    x1\n", + "    X_2\n", + "    nombre_3\n", + "    NombreApellido\n", + "```\n", + "Ten en cuenta que hay palabras reservadas que no puede usar; son las [palabras reservadas de Python](https://es.wikibooks.org/wiki/Python/Generalidades/Palabras_reservadas,_operadores_y_s%C3%ADmbolos_del_lenguaje).\n", + "  \n", + "Asignemos ahora algunos valores a las variables y realicemos algunas operaciones con ellos:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "x = 3 " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "y = 4.5" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##### Ejercicio:\n", + "Imprime los valores de las variables `x` y` y`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Hagamos algunas operaciones aritméticas con nuestras nuevas variables:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "x + y" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "2**x" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "y - 3" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Y ahora, revisemos los valores de `x` y` y`. ¿Siguen siendo los mismos que cuando los asignaste?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(x)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(y)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Variables de cadena\n", + "\n", + "Además del nombre y el valor, las variables de Python corresponden a un cierto _tipo_ de dato: el tipo del valor al que se refiere. Por ejemplo, un valor entero tiene el tipo `int`, y un nmero real tiene el tipo` float`. Una cadena de texto es una variable que consiste en una secuencia de caracteres marcados por dos comillas, y tiene el tipo `str`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "z = 'this is a string'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "w = '1'" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "¿Qué pasa si intentas \"unir\" dos cadenas de texto?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "z + w" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "La operación anterior se llama _concatenación_: los dos strings o cadenas de texto se han reunido en una sola. Interesante, ¿eh? Sin embargo, mira esto:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "x + w" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "_¡Error!_ ¿Por qué? Examinemos lo que Python acaba de decir y exploremos lo que está sucediendo.\n", + "\n", + "Python es un lenguaje dinámico, lo que significa que no necesitas especificar un tipo para definir un objeto existente. El apodo humorístico para esto es \"duck typing\" (comportamiento de pato):\n", + "\n", + "#### \"Cuando veo un ave que camina como un pato, nada como un pato y suena como un pato, a esa ave yo la llamo un pato.\".\n", + "\n", + "En otras palabras, una variable tiene un tipo, pero no necesitamos especificarlo. Simplemente se comportará como se supone que debe hacerlo cuando operemos con él (graznará y caminará como fue la intención de la naturaleza).\n", + "\n", + "Pero a veces es necesario asegurarse de conocer el tipo de una variable. Afortunadamente, Python ofrece una función para encontrar el tipo de variable: `type()` (tipo, en inglés)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "type(x)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "type(w)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "type(y)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Más asignaciones\n", + "\n", + "¿Qué sucede si se desea asignar a una nueva variable el resultado de una operación que involucra otras variables? ¡No hay problema!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sum_xy = x + y\n", + "diff_xy = x - y" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print('The sum of x and y is:', sum_xy)\n", + "print('The difference between x and y is:', diff_xy)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Observa lo que hicimos arriba: utilizamos la función `print()` con una cadena de texto (string), seguido de una variable, y Python imprimió una combinación útil del mensaje y el valor de la variable. Un consejo profesional: Imprime mensajes que sean fáciles de leer para otras personas. Veamos ahora el tipo de las nuevas variables que acabamos de crear:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "type(sum_xy)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "type(diff_xy)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##### Discute con tu vecino:\n", + "¿Puedes resumir lo que hicimos arriba?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Variables especiales\n", + "\n", + "Python tiene variables especiales que están integradas en el lenguaje. Estos son:\n", + "`True`,` False`, `None` y` NotImplemented`.\n", + "Por ahora, veremos solo los primeros tres de estos.\n", + "\n", + "** Las variables booleanas ** se utilizan para representar valores de verdad, y pueden tomar uno de dos valores posibles: `True` (Verdadero) y ` False` (Falso).\n", + "_Expresiones lógicas_ devuelven booleanos. Aquí está la expresión lógica más simple, usando la palabra reservada `not`:\n", + "\n", + "```Python\n", + "  not True\n", + "```\n", + "\n", + "Retorna... lo has adivinado... `False` (Falso).\n", + "\n", + "La función de Python `bool()` devuelve un valor de verdad asignado a cualquier argumento. Cualquier número que no sea cero tiene un valor de verdad de `True`, así como cualquier cadena o lista no vacía. El número cero y cualquier cadena o lista vacía tendrán un valor de verdad de `False`. Ahora exploremos la función `bool()` con varios argumentos." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "bool(0)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "bool('Do we need oxygen?')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "bool('We do not need oxygen')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**None no es cero **: `None` (ninguno, nada) es una variable especial que indica que no se asignó ningún valor o que un comportamiento no está definido. Es diferente del valor cero, una cadena vacía o algún otro valor nulo.\n", + "\n", + "Puedes verificar que no sea cero tratando de agregarlo a un número. Veamos qué pasa cuando intentamos eso:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "a = None\n", + "\n", + "b = 3" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "a + b" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Operadores lógicos y de comparación\n", + "\n", + "Los operadores de comparación de Python son: `<`, `<=`, `>`, `> =`, `==`, `!=`. Comparan dos objetos y devuelven `True` o` False`: menor, menor o igual, mayor, mayor o igual, igual, distinto. ¡Inténtalo!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "x = 3\n", + "y = 5" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "x > y" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Podemos asignar el valor de verdad de una operación de comparación a un nuevo nombre de variable:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "z = x > y" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "z" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "type(z)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Los operadores lógicos son los siguientes: `and` (y, en inglés), `or` (o, en inglés), y `not` (no, en inglés). Funcionan igual que en el inglés. Una expresión lógica con `and` es verdadera (`True`) sólo si ambos operandos son verdaderos. Una expresión con `or` es verdadera (`True`) cuando cualquiera de los operandos es verdadero. Y la palabra clave `not` siempre niega la expresión que le sigue.\n", + "\n", + "Hagamos algunos ejemplos:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "a = 5\n", + "b = 3\n", + "c = 10" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "a > b and b > c" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Recuerde que el operador lógico `and` es `True` solo cuando ambos operandos son `True`. En el caso anterior, el primer operando es `True` pero el segundo es` False`.\n", + "\n", + "Si probamos la operación `or` usando los mismos operandos, deberíamos obtener un `True`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "a > b or b > c" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Y la negación del segundo operando resulta en ..." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "not b > c" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "¿Qué pasa si negamos el segundo operando en la operación `and` de arriba?\n", + "\n", + "##### Nota:\n", + "\n", + "Tenga cuidado con el orden de las operaciones lógicas. El orden de precedencia en la lógica es:\n", + "\n", + "1. Negación (`not`)\n", + "2. Y (`and`)\n", + "3. O (`or`)\n", + "\n", + "Si no recuerda esto, asegúrese de usar paréntesis para indicar el orden que desea." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##### Ejercicio:\n", + "\n", + "¿Qué está pasando en el caso a continuación? Juega con operadores lógicos y prueba algunos ejemplos." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "a > b and not b > c" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Lo que hemos aprendido\n", + "\n", + "* Como se usa la función `print()`. El concepto de _función_.\n", + "* Usar Python como una calculadora.\n", + "* Conceptos de variable, tipo, asignación.\n", + "* Variables especiales: `True`,` False`, `None`.\n", + "* Operaciones compatibles, operaciones lógicas.\n", + "* Lectura de mensajes de error." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Referencias\n", + "\n", + "A lo largo de este módulo de curso, vamos a usar las siguientes referencias:\n", + "\n", + "1. _Effective Computation in Physics: Field Guide to Research with Python_ (Computación Eficaz en Física: Guía de campo para la investigación con Python, 2015). Anthony Scopatz & Kathryn D. Huff. O'Reilly Media, Inc.\n", + "2. _Python for Everybody: Exploring Data Using Python 3_ (Python para todos: explorando datos con Python 3, 2016). Charles R. Severance. [PDF available](http://do1.dr-chuck.com/pythonlearn/EN_us/pythonlearn.pdf)\n", + "3. _Think Python: How to Think Like a Computer Scientist_ (Piensa en Python: Aprenda a pensar como un cientista computacional, 2012). Allen Downey. Green Tea Press. [PDF available](http://greenteapress.com/thinkpython/thinkpython.pdf)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Lecturas recomendadas\n", + "\n", + "- [\"Yes, Python is Slow, and I Don’t Care\"](https://hackernoon.com/yes-python-is-slow-and-i-dont-care-13763980b5a1) (\"Sí, Python es lento, y no me importa\") por Nick Humrich, en Hackernoon. Conviene omitir la parte de microservicios, que es un poco especializada, y continuar después de la foto de las luces del automóvil en movimiento.\n", + "- [\"Why I Push for Python\"](http://lorenabarba.com/blog/why-i-push-for-python/) (Por qué apoyo a Python), por la profesora Lorena A. Barba (2014). Esta publicación de blog obtuvo un poco de interés en [Hacker News](https://news.ycombinator.com/item?id=7760870)." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Ejecuta esta celda para cargar el notebook con estilo, \n", + "# pero puedes ignorar su contenido.\n", + "from IPython.core.display import HTML\n", + "css_file = '../style/custom.css'\n", + "HTML(open(css_file, \"r\").read())" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.5.2" + }, + "widgets": { + "state": {}, + "version": "1.1.2" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/notebooks_es/2_Strings_y_listas_en_accion.ipynb b/notebooks_es/2_Strings_y_listas_en_accion.ipynb new file mode 100644 index 0000000..600701a --- /dev/null +++ b/notebooks_es/2_Strings_y_listas_en_accion.ipynb @@ -0,0 +1,1814 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "###### Contenido bajo licencia Creative Commons Attribution CC-BY 4.0, código bajo licencia BSD 3-Clause © 2017 L.A. Barba, N.C. Clementi" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Jugando con datos en Jupyter\n", + "\n", + "Esta es la segunda lección de nuestro curso en _\"Cálculos Computacionales en Ingeniería\"_. En la primera lección, [_Interactuando con Python_](./1_Interactuando_con_Python.ipynb), usamos **IPython**, el shell interactivo de Python. Es genial escribir expresiones de Python de una sola línea y obtener los resultados de forma interactiva. Sin embargo, aunque no lo creas, ¡hay cosas más increíbles!\n", + "\n", + "En esta lección, continuarás usando Python para jugar con datos, pero lo harás en un **Jupyter Notebook**. Esta misma lección está escrita en un Jupyter Notebook. ¿Listo? No te arrependirás." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## ¿Qué es Jupyter?\n", + "\n", + "Jupyter es un conjunto de herramientas de código abierto para la informática interactiva y exploratoria. Trabajarás directamente en tu navegador web, que se convierte en la interfaz de usuario a través de la cual Jupyter te proporciona un explorador de archivos (el _dashboard_) y un documento: el **notebook**.\n", + "\n", + "Un Jupyter Notebook puede contener: entrada y salida de código, texto con formato, imágenes, videos, bonitas ecuaciones matemáticas y mucho más. El código de la computadora es completamente _ejecutable_, lo que significa que puede ejecutar el código, directamente en el documento, y obtener la salida de ese código en el navegador. Esta forma interactiva de computación, mezclada con la narrativa multimedia, permite contar una historia (incluso de manera individual y personal) con súperpoderes computacionales." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Trabajar en Jupyter\n", + "\n", + "Varias cosas te parecerán contraintuitivas al principio. Por ejemplo, la mayoría de las personas están acostumbradas a iniciar aplicaciones en sus computadoras haciendo clic en algún ícono: esto es lo primero que se debe \"desaprender\". Jupyter se lanza desde la _línea de comando_ (como cuando lanzaste IPython). Además, tenemos dos tipos de contenido: código y texto (markdown), que se manejan de forma un poco diferente. El hecho de que el navegador sea una interfaz para un motor de cómputo (llamado \"kernel\") lleva a un mantenimiento interno adicional (como cerrar el kernel). ¡Pero te acostumbrarás bastante rápido!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Iniciando Jupyter\n", + "\n", + "La forma estándar de iniciar Jupyter es escribir en la interfaz de línea de comandos:\n", + "\n", + "`jupyter notebook`\n", + "\n", + "Presiona enter y ... ¡listo!\n", + "Después de un breve tiempo de configuración, tu navegador predeterminado se abrirá con la aplicación Jupyter. Debería ser similar a la siguiente captura de pantalla, pero es posible que se vea una lista distinta de archivos y carpetas, según la ubicación de tu computadora.\n", + "\n", + "##### Nota:\n", + "\n", + "No cierres la ventana del terminal que lanzó Jupyter mientras todavía está trabajando en Jupyter. Si necesitas hacer otras tareas en la línea de comando, abre una nueva ventana de terminal.\n", + "\n", + "---\n", + "\n", + "Para iniciar un nuevo Jupyter Notebook, haz clic en la esquina superior derecha, donde dice **Nuevo** o **New**, y selecciona `Python 3`. Deberías tener algo similar a la siguiente captura de pantalla:\n", + "\n", + "\n", + "\n", + "#### Captura de pantalla del dashboard de Jupyter, abierto en el navegador.\n", + "\n", + "---\n", + "\n", + "Aparecerá una nueva pestaña en tu navegador web y verás un notebook vacío, con una sola línea de entrada, esperando que ingreses algún código, como en la siguiente captura de pantalla:\n", + "\n", + "\n", + "\n", + "#### Captura de pantalla que muestra cómo crear un nuevo cuaderno.\n", + "\n", + "---\n", + "\n", + "\n", + "El notebook se abre de manera predeterminada con una sola celda de código vacía. Intenta escribir allí un código Python y ejecútalo presionando `[shift] + [enter]`.\n", + "\n", + "\n", + "\n", + "#### Captura de pantalla que muestra un nuevo cuaderno vacío.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Celdas de notebook\n", + "\n", + "El cuaderno Jupyter usa _celdas_ (_cells_), que corresponden a bloques que pueden contener fragmentos de texto y código. Cualquier contenido de texto se ingresa en una celda *Markdown*: contiene texto que puede formatear con marcadores simples para obtener encabezados, negrita, cursiva, viñetas, hipervínculos y más.\n", + "\n", + "Markdown es fácil de aprender, consulte la sintaxis en la página web [\"Daring Fireball\"](https://daringfireball.net/projects/markdown/syntax) (por John Gruber). Algunos consejos:\n", + "\n", + "* Para crear un título, usa `#` para comenzar la línea: `# Título`\n", + "* Para crear el siguiente encabezado, use `##` (y así sucesivamente): `## Subtítulo`\n", + "* Para poner en cursiva una palabra o frase, enciérrelo en asteriscos (o con líneas inferiores): `*cursiva*` o `_cursiva_`\n", + "* Para que sea negrita, enciérrelo con dos asteriscos: `**en negrita**`\n", + "* Para hacer un hipervínculo, use corchetes cuadrados y redondos: `[texto para el enlace](url del enlace)`\n", + "\n", + "El contenido de código ejecutable se ingresa en celdas de código. Usaremos el kernel de IPython (\"kernel\" es el nombre utilizado para el motor de computación), pero debes saber que Jupyter puede utilizarse con muchos lenguajes de computación diferentes. Es in-cre-í-ble.\n", + "\n", + "Una celda de código te mostrará un espacio para ingresar código:\n", + "\n", + "`In []:`\n", + "\n", + "Una vez que agregues código y lo ejecutes, Jupyter agregará un número de identificación a la celda de entrada, y producirá una salida marcada así:\n", + "\n", + "`Out [1]:`\n", + "\n", + "##### Un poco de historia:\n", + "\n", + "Markdown fue co-creado por el legendario pero trágico [Aaron Swartz](https://es.wikipedia.org/wiki/Aaron_Swartz). El documental biográfico sobre él se llama [The Internet's Own Boy\"](https://en.wikipedia.org/wiki/The_Internet%27s_Own_Boy) y puedes verlo en YouTube o Netflix. ¡Recomendado!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Computación interactiva en el cuaderno\n", + "\n", + "Observa los iconos en el menú de Jupyter como se muestran en las capturas de pantalla anteriores de este notebook. El primer ícono a la izquierda (un disquete de los antiguos) es para guardar el notebook. Puedes agregar una nueva celda presionando el gran botón **+**. Además existen los los botones cortar, copiar y pegar. Las flechas son para mover la celda actual hacia arriba o hacia abajo. Existe un botón para \"ejecutar\" una celda de código (ejecutar el código), el icono cuadrado significa \"detener\" y la flecha circular para \"reiniciar\" el kernel del notebook (si el cálculo está tomando demasiado tiempo, por ejemplo). Además, se puede seleccionar el tipo de celda: código o texto markdown (u otros que puedes ignorar por ahora).\n", + "\n", + "Puedes probar una celda de código escribiendo algunas operaciones aritméticas. Como vimos en nuestra primera lección, los operadores de Python son:\n", + "```python\n", + "    + - * / ** % //\n", + "```\n", + "\n", + "Existe la suma, la resta, la multiplicación y la división. Los últimos tres operadores son _exponente_ (elevar a la potencia), _módulo_ (divide y devuelve el resto) y _división entera_.\n", + "\n", + "Tecleando `[shift] + [enter]` se ejecutará la celda y obtendrás la salida en una nueva línea, etiquetada como `Out [1]`. La numeración aumenta cada vez que ejecuta una celda.\n", + "\n", + "##### ¡Inténtalo!\n", + "\n", + "Agrega una celda con el botón más, ingresa algunas operaciones, y utiliza `[shift] + [enter]` para ejecutar." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Todo lo que hicimos usando IPython lo podemos hacer en celdas de código dentro de un Jupyter notebook. Prueba algunas de las cosas que aprendimos en la lección 1:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(\"¡Hola mundo!\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "x = 2**8\n", + "x < 64" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Modo de edición y modo de comando\n", + "\n", + "Una vez que haces click en una celda del notebook para seleccionarla, puedes interactuar con ella de dos maneras o _modos_. Más adelante, si revisas este material nuevamente y en mayor profundidad, puedes leer más sobre esto en la referencia número 1 al final de este notebook.\n", + "\n", + "**Modo de edición:**\n", + "\n", + "* Ingresamos **al modo de edición** presionando 'Enter' o haciendo doble clic en la celda.\n", + "\n", + "* Sabemos que estamos en este modo cuando vemos un borde de celda verde y un mensaje en el área de la celda.\n", + "\n", + "* Cuando estamos en modo de edición, podemos escribir en la celda, como un editor de texto normal, tanto para código como para texto markdown.\n", + "\n", + "\n", + "**Modo de comando:**\n", + "\n", + "* Ingresamos en **modo de comando** presionando `Esc` o haciendo clic fuera del área de la celda.\n", + "\n", + "* Sabemos que estamos en este modo cuando vemos un borde de celda gris con un margen azul izquierdo.\n", + "\n", + "* En este modo, ciertas teclas permiten utilizar atajos de teclado (accesos directos) para ayudar con acciones comunes.\n", + "\n", + "Puede encontrar una lista de los accesos directos seleccionando `Help->Keyboard Shortcuts` (`Ayuda-> Atajos de teclado`) desde la barra de menú del notebook. Puedes continuar con esto más adelante, pero se vuelve más útil cuanto más usas Jupyter. ¡Siempre es más eficiente conocer atajos de teclado!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Cómo cerrar el kernel y salir\n", + "\n", + "Cerrar la pestaña del navegador donde has estado trabajando en un notebook no \"cierra\" inmediatamente el kernel. A veces necesitas hacer un poco de limpieza antes.\n", + "\n", + "Una vez que cierres un notebook, verás en la aplicación Jupyter principal que el archivo del notebook tiene un símbolo con un libro verde al lado. Deberías hacer click en el cuadro a la izquierda de ese símbolo, y luego hacer clic donde dice **Shutdown** o **Apagar**. No necesitas hacer esto todo el tiempo, pero si tienes varios notebooks abiertos, permite disminuir los recursos utilizados.\n", + "\n", + "Del mismo modo, Jupyter aún se está ejecutando incluso después de cerrar la pestaña del navegador que tiene abierto Jupyter. Para salir de la aplicación Jupyter, debe ir al terminal de comando que se utilizó para abrir Jupyter, y hacer `[Ctrl] + [c]` para salir." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Nbviewer\n", + "\n", + "[Nbviewer](http://nbviewer.jupyter.org/) es un servicio web gratuito que le permite compartir versiones estáticas de notebooks, como si se tratara de una página web. Si un archivo de computadora portátil está disponible públicamente en la web, puede verlo ingresando su URL en la página web de nbviewer y presionando el botón **Go!**. El notebook se representará como una página estática: los visitantes podrán leer todo, pero no podrán interactuar con el código." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Juega con strings en Python\n", + "\n", + "Sigamos jugando con strings o cadenas de texto, pero ahora trabajaremos en un Jupyter Notebook (en lugar de IPython). Te recomendamos que abras un nuevo notebook limpio para seguir los ejemplos de esta lección y escribas los comandos que ve. Escribe tu mismo, letra a letra, todos los comandos que quieras probar. Si sólo copias y pegas, ahorrarás tiempo, pero aprenderás poco y retendrás aún menos. ¡Tipea todo!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "str_1 = 'hola'\n", + "str_2 = 'mundo'" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Recuerde que podemos concatenar (\"unir\") los strings, por ejemplo:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "new_string = str_1 + str_2\n", + "print(new_string)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "¿Qué ocurre si queremos agregar un espacio que separa `hola` from `mundo`? Añadimos directamente la cadena `' '` en el medio de las dos variables. Un espacio es un carácter de texto (NdlT: se llama character en inglés, abreviado char para los amigos)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "my_string = str_1 + ' ' + str_2\n", + "print(my_string)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##### Ejercicio:\n", + "\n", + "Crea una nueva variable de cadena que agrega tres signos de admiración al final de `my_string`." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "collapsed": true + }, + "source": [ + "### Indexación\n", + "\n", + "Podemos acceder a cada carácter de texto por separado en una cadena de texto (o incluso, un trozo continuo de la misma) usando _índices_: enteros que denotan la posición del carácter en la cadena de texto. Los índices van entre corchetes, tocando el nombre de la variable a la derecha. Por ejemplo, para acceder al primer elemento de `new_string`, debemos ingresar` new_string[0]`. ¡Sí! en Python comenzamos a contar desde 0 (y hace mucho sentido)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "my_string[0]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#Si queremos el tercer elemento:\n", + "my_string[2]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Es posible que hayas notado que en la celda de arriba tenemos una línea antes del código que comienza con el signo `#`. Esa línea parece ser ignorada por Python: ¿sabes por qué?\n", + "\n", + "Es un **comentario**: cuando quieras comentar su código de Python, coloca un `#` delante del comentario. Por ejemplo:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "my_string[1] #así accedemos al segundo elemento del string" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "¿Cómo sabemos el índice del último elemento en la cadena?\n", + "\n", + "Python tiene una función incorporada llamada `len()` (abreviación de length, que significa largo o longitud en inglés) que proporciona la información sobre la longitud de un objeto:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "len(my_string)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "¡Estupendo! Ahora sabemos que `my_string` tiene diez caracteres. ¿Qué sucede si ingresamos este número como índice?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "my_string[10]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Oops. Tenemos un error: ¿por qué? La longitud de `my_string` es diez. Pero el número entero 10 no funciona como un índice. Si esperabas obtener el último elemento, es porque olvidaste que Python comienza a contar desde cero. No te preocupes: lleva un tiempo acostumbrarse.\n", + "\n", + "El mensaje de error dice que el índice está fuera de rango: esto es porque el índice del _último elemento_ siempre será: `len (cadena) - 1`. En nuestro caso, ese número es 9. Probémoslo." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "my_string[9]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Python también ofrece una forma inteligente y elegante de obtener el último elemento, por lo que no es necesario calcular la longitud y restar uno: se puede utilizar simplemente un `-1` para el índice. ¿Cómo no enamorarse de esta característica?:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "my_string[-1]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "¿Qué pasa si usamos un `-2` como índice?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "my_string[-2]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Obtenemos la letra `d` del string `hola mundo`. ¡Python es tan inteligente que puede contar hacia atrás!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Cortar cadenas\n", + "\n", + "A veces, queremos obtener más de un elemento: es posible que deseemos una sección de la cadena. Lo hacemos utilizando la notación de _slicing_ (corte) entre corchetes. Para esto se usa `[inicio:fin]`, donde `inicio` es el índice para comenzar el corte, y `fin` es el índice (no incluido) para terminar el corte. Por ejemplo, para tomar la palabra `hola` de nuestra cadena utilizamos:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "my_string[0:4]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Puedes omitir el índice `inicio` si desea cortar desde el principio de la cadena, y puedes omitir el `fin` si deseas llegar hasta el final de la cadena. Por ejemplo, si queremos tomar la palabra `'mundo'` de ` my_string`, podríamos hacer lo siguiente:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "my_string[5:]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Una forma útil de visualizar segmentos es imaginar que los índices apuntan a los espacios _entre_ caracteres en la cadena. De esta forma, cuando escriba `my_string[i]`, se estaría refiriendo al \"carácter a la derecha de `i` \"(Referencia 2).\n", + "\n", + "Mira el diagrama a continuación (NdlT: Engineer significa ingeniero en inglés). Comenzamos a contar a cero; la letra `g` está a la derecha del índice 2. Entonces, si queremos obtener la subcadena `'gin'` de `'engineer'`, necesitamos `[inicio:fin] = [2:5]`.\n", + "\n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "collapsed": true + }, + "source": [ + "¡Inténtalo tú mismo!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Definir un string\n", + "eng_string = 'engineer'\n", + "\n", + "# Obtener el sub-string 'gin'\n", + "eng_string[2:5] # O equivalentemente, eng_string[2:-3]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##### Ejercicios:\n", + "\n", + "1. Define una cadena de texto llamada `'banana'` e imprime la primera y última `'a'`.\n", + "2. Usando el mismo string, obtén las 2 combinaciones posibles que corresponden a la palabra \"ana\" e imprímelas.\n", + "3. Crea tu propio ejercicio de slicing y pídales a sus compañeros que lo intenten (trabajar en grupos de 3)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Las siguientes líneas contienen las soluciones; para revelar la respuesta, selecciona las líneas con el mouse:\n", + " \n", + "Ejercicio de solución 1:\n", + "\n", + " b = 'banana' \n", + "\n", + " print (b [1]) \n", + "\n", + " print (b [-1]) \n", + "\n", + "\n", + "Ejercicio de solución 2:\n", + "\n", + " print (b [1: 4]) \n", + "\n", + " print (b [3:]) " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### ¿Qué más podemos hacer con las cadenas?\n", + "\n", + "Python tiene muchas funciones útiles para cadenas. Aprenderás algunas de ellos en esta sección. Un detalle técnico: en Python, algunas funciones están asociadas a una clase particular de objetos (por ejemplo, strings). La palabra **método** (method) se usa en este caso, y tenemos una nueva forma de llamarlos: el operador de punto. Es un poco contra-intuitivo que el nombre del método viene después del punto, mientras que el nombre del objeto en particular en el que actúa es lo primero. Así, por ejemplo, tendríamos: `mystring.method()`.\n", + "\n", + "Si tiene curiosidad acerca de los muchos métodos disponibles para strings, puedes ir a la sección \"Métodos de strings incorporados\" en este [tutorial](https://www.tutorialspoint.com/python3/python_strings.htm).\n", + "\n", + "Usaremos una cita de Albert Einstein como en un string y aplicaremos algunos métodos de cadena útiles para ejemplificar." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Everybody is a genius. But if you judge a fish by its ability to climb a tree, \n", + "# it will live its whole life believing that it is stupid\n", + "\n", + "AE_quote = \"Todas las personas son genios. Pero si juzgas a un pez por su habilidad de trepar un árbol, creerá toda su vida que es un idiota.\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "El método **`count()`** retorna el número de ocurrencias de un substring determinado en un rango. Los argumentos para el rango son opcionales.\n", + "\n", + "*Sintaxis:*\n", + "\n", + "`str.count(substr, inicio, fin)`\n", + "\n", + "Aquí, `inicio` y `fin` son enteros que indican los índices donde comenzar y finalizar el conteo del string `substr`. Por ejemplo, si queremos saber cuántas letras `'e'` tenemos en toda la cadena, podemos hacer:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "AE_quote.count('e')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Si queremos saber cuántos de esos carácteres `'e'` están en el rango `[0:20]`, hacemos:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "AE_quote.count('e', 0, 20) # O equivalentemente, AE_quote[:20].count('e')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Podemos buscar cadenas más complejas, por ejemplo:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "AE_quote.count('un')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "El método **find()** nos dice si un string `substr` ocurre en la cadena en la que estamos aplicando el método. Los argumentos para el rango son opcionales.\n", + "\n", + "*Sintaxis:*\n", + "\n", + "`str.find (substr, inicio, fin)`\n", + "\n", + "Donde `inicio` y `fin` son índices que indican dónde comenzar y terminar el slicing para aplicar el método `find()`.\n", + "\n", + "Si la cadena `substr` está en la cadena original, el método `find()` devolverá el índice donde comienza la subcadena, de lo contrario devolverá `-1`.\n", + "\n", + "Por ejemplo, busquemos la palabra `\"pez\"` en la cita de Albert Einstein." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "AE_quote.find('pez')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Si conocemos la longitud (largo) del substring, ahora podemos aplicar la notación de corte para hallar la palabra `\"pez\"`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "len('pez')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "AE_quote[51: 51 + len('pez')]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "O equivalentemente" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "s = 'pez'\n", + "i = AE_quote.find(s)\n", + "AE_quote[i: i + len(s)]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Veamos qué sucede cuando tratamos de buscar una cadena que no está en la cita." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "AE_quote.find('PEZ')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Devuelve `-1` ... pero cuidado, ¡eso no significa que la posición esté al final de la cadena original! Si leemos la [documentación](https://docs.python.org/3/library/stdtypes.html#string-methods), confirmamos que un valor devuelto de `-1` indica que la subcadena que estamos buscar _no está en la cadena_ en la que estamos buscando.\n", + "\n", + "Un método similar es **`index()`**: funciona como el método `find()`, pero genera un error si no se encuentra la cadena que estamos buscando.\n", + "\n", + "*Sintaxis:*\n", + "\n", + "`str.index(substr, start, end)`\n", + "\n", + "¡Por eso siempre es importante verificar la documentación!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "AE_quote.index('pez')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "AE_quote.index('PEZ')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "En el ejemplo anterior, usamos la función `len()` para calcular la longitud de la cadena `'pez'`, y usamos el resultado para calcular el índice final. Sin embargo, si la cadena es demasiado larga, tener una línea que calcule la longitud puede ser inconveniente o puede hacer que su código parezca desordenado. Para evitar esto, podemos usar los métodos `find()` o `index()` para calcular la posición final. En el ejemplo de \"pez\", podríamos buscar el índice de la palabra \"por\" (la palabra que sigue a \"pez\") y restar 1 de ese índice para obtener el índice que corresponde al espacio correcto después de `'fish'`. ¡Hay muchas formas de hacer slicing de cadenas de texto, sólo limitadas por tu imaginación!\n", + "\n", + "##### Nota:\n", + "Recuerde que el índice final no es inclusivo, por lo que queremos el índice del espacio que sigue al string `'pez'`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "idx_ini = AE_quote.index('pez')\n", + "idx_fin = AE_quote.index('por') - 1 # Se resta 1 para obtener el indice correcto del espacio después de pez." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "AE_quote[idx_ini:idx_fin]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##### Ejercicios:\n", + "\n", + "1. Usa el método `count()` para contar cuántas letras '`a'` están en `AE_quote`?\n", + "2. Usando el mismo método, ¿cuántas letras aisladas `'a'` están en `AE_quote`?\n", + "3. Usa el método `index ()` para encontrar la posición de las palabras `'genio'`,`'juzgas'` y `'árbol'` en `AE_quote`.\n", + "4. Con la sintaxis de corte, extrae las palabras del ejercicio 3 de `AE_quote`." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Existen otros dos métodos de cadena resultan útiles cuando se trabaja con textos y se necesita limpiar, separar o categorizar partes del texto.\n", + "\n", + "Para demostrarlos, vamos a trabajar con una cadena diferente, una cita de Eleanor Roosevelt:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Great minds discuss ideas; average minds discuss events; small minds discuss people.\n", + "ER_quote = \" Grandes mentes discuten sobre ideas; mentes promedio discuten sobre eventos; mentes pequeñas discuten sobre personas. \"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Ten en cuenta que la cadena de texto que definimos anteriormente contiene espacios en blanco adicionales al principio y al final. En este caso, fue realizado a propósito, pero a menudo hay espacios extra molestos cuando leemos texto de un archivo (quizás debido a la sangría de un párrafo).\n", + "\n", + "Las cadenas tienen un método que nos permite deshacernos de esos espacios en blanco adicionales.\n", + "\n", + "El método **`strip()`** devuelve una copia de la cadena de texto en la que se eliminan todos los caracteres dados como argumento desde el principio y el final de la cadena.\n", + "\n", + "*Sintaxis:*\n", + "\n", + "`str.strip ([chars])`\n", + "\n", + "El argumento predeterminado es el carácter de espacio. Por ejemplo, si queremos eliminar los espacios en blanco en `ER_quote` y guardar el resultado en `ER_quote`, podemos hacer:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ER_quote = ER_quote.strip()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ER_quote" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Supongamos que quieres quitar el período al final; podrías hacer lo siguiente:\n", + "\n", + "`ER_quote = ER_quote.strip('.')`\n", + "\n", + "Pero si no queremos mantener los cambios en nuestra variable de cadena, no sobrescribimos la variable como hicimos anteriormente. Veamos cómo se ve:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ER_quote.strip('.')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Verifique la variable de cadena para confirmar que no cambió (todavía tiene el punto al final):" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ER_quote" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Otro método útil es **`startswith()`**, para averiguar si una cadena comienza con un cierto carácter.\n", + "Más adelante en esta lección veremos un ejemplo más interesante; pero por ahora, solo \"verifiquemos\" si nuestra cadena comienza con la palabra \"genial\"." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ER_quote.startswith('grandes')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "La salida es `False` porque la palabra no está en mayúscula. Las letras mayúsculas y minúsculas son caracteres distintos." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ER_quote.startswith('Grandes')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Es importante mencionar que no es necesario que coincidamos con la primera palabra, sino con una combinación arbitraria de caracteres." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ER_quote.startswith('Gra')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "El último método de cadena que mencionaremos es **`split()`**: devuelve una **lista** de todas las palabras en una cadena. También podemos definir un separador y dividir nuestra cadena de acuerdo con ese separador, y opcionalmente podemos limitar el número de divisiones a `num`.\n", + "\n", + "*Sintaxis:*\n", + "\n", + "`str.split(separator, num)`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(AE_quote.split())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(ER_quote.split())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Vamos a dividir el `ER_quote` utilizando un carácter distinto, un punto y coma (`;`):" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + " print(ER_quote.split(';'))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##### Reflexionando...\n", + "\n", + "¿Notan algo nuevo en la salida de las llamadas `print()`?\n", + "¿Que significan esos paréntesis cuadrados, `[]`?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Juega con listas de Python\n", + "\n", + "Los corchetes o paréntesis cuadrados indican una **lista** de Python. Una lista es un tipo de datos que ya viene en Python que consiste en una secuencia de valores, por ejemplo, números o strings. Las listas funcionan de manera similar a las cadenas de texto: sus elementos están numerados a partir de cero, la función `len()` regresa el número de elementos, se pueden manipular con notación de slicing, y así sucesivamente.\n", + "\n", + "La forma más fácil de crear una lista es incluir una secuencia de valores separados por comas entre corchetes:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# A list of integers \n", + "[1, 4, 7, 9]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# A list of strings\n", + "['manzana', 'banana', 'naranja']" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# A list with different element types\n", + "[2, 'manzana', 4.5, [5, 10]]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "En este último ejemplo, el último elemento de la lista es en realidad _otra lista_. ¡Sí! No hay problema. Una lista puede contener elementos de cualquier tipo.\n", + "\n", + "También podemos asignar listas a nombres de variables, por ejemplo:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "integers = [1, 2, 3, 4, 5]\n", + "fruits = ['manzana', 'banana', 'naranja']" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(integers)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(fruits)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "new_list = [integers, fruits]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(new_list)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Ten en cuenta que esta `new_list` tiene sólo 2 elementos. Podemos verificarlo con la función `len()`:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "len(new_list)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Cada elemento de `new_list` es, por supuesto, otra lista.\n", + "Al igual que con las cadenas, accedemos a los elementos de la lista con índices y notación de slicing. El primer elemento de `new_list` es la lista de enteros del 1 al 5, mientras que el segundo elemento es la lista de tres nombres de frutas." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "new_list[0]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "new_list[1]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Accessing the first two elements of the list fruits\n", + "fruits[0:2]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##### Ejercicios:\n", + "\n", + "1. De la lista `enteros`, toma la sub-lista `[2, 3, 4]` y luego `[4, 5]`.\n", + "2. Crea tu propia lista y diseña un ejercicio para agarrar slices, trabajando con tus compañeros de clase." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Agregar elementos a una lista\n", + "\n", + "Podemos agregar elementos a una lista usando el método **append()**: agrega un objeto que pasamos a una lista existente. Por ejemplo, para agregar el elemento 6 a nuestra lista `integers`, podemos hacer:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "integers.append(6)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Comprobemos que la lista ahora tiene un 6 al final:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(integers)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Lista de miembros\n", + "\n", + "¡Comprobar la pertenencia a una lista en Python es bastante similar al idioma inglés!\n", + "\n", + "*Sintaxis*\n", + "\n", + "Para verificar si un elemento está **en** una lista usamos `in`:\n", + "\n", + "`elemento in lista`\n", + "\n", + "Para verificar si un elemento **no está en** una lista usamos `not in`:\n", + "\n", + "`elemento not in lista`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "'fresa' in fruits" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "'fresa' not in fruits" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##### Ejercicios\n", + "\n", + "1. Agrega dos frutas diferentes a la lista `fruits`.\n", + "2. Comprueba si `'mango'` está en tu nueva lista` fruits`.\n", + "3. Dada la lista `lista = [1, 2, 3, '4', [5, 'seis'], [7]]` ejecuta lo siguiente en celdas separadas y analiza el resultado con tus compañeros de clase:\n", + "\n", + "```Python\n", + "4 in lista\n", + "5 in lista\n", + "7 in lista\n", + "[7] in lista\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Modificar elementos de una lista\n", + "\n", + "No sólo podemos agregar elementos a una lista, también podemos modificar un elemento específico.\n", + "Reutilicemos la lista del ejercicio anterior y reemplacemos algunos elementos." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "lista = [1, 2, 3, '4', [5, 'seis'], [7]]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Podemos encontrar la posición de un cierto elemento con el método `index()`, al igual que con las cadenas. Por ejemplo, si queremos saber dónde está el elemento `'4'`, podemos hacer:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "lista.index('4')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "lista[3]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Vamos a reemplazarlo con el valor entero `4`:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "lista[3] = 4" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "lista" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "4 in lista" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##### Ejercicio\n", + "Reemplaza el último elemento de `lista` con algo diferente." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Poder modificar elementos en una lista es una \"propiedad\" de las listas de Python; otros objetos Python que veremos más adelante en el curso también se comportan así, pero no todos los objetos Python. Por ejemplo, no puede modificar elementos en un string. Si lo intentamos, Python se quejará.\n", + "\n", + "¡No importa! Vamos a intentarlo. Uno de los principios de computación es comprobar e intentar cosas, aunque no funcionen:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "string = 'Esto es un string.'" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Supongamos que queremos reemplazar el período ('.') Por un signo de exclamación ('!'). ¿Podemos modificar directamente este elemento de cadena?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "string[-1]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "string[-1] = '!'" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "¡Te lo dije! Python confirma que no podemos cambiar los elementos de una cadena por asignación de elemento." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Cadenas y listas en acción\n", + "\n", + "Has aprendido muchas cosas sobre cadenas de texto y listas en esta lección, y probablemente estás ansioso por ver cómo aplicarlo a una situación realista. Creamos un [ejemplo completo](./3_Jugando_con_archivo_de_cursos.ipynb) en un notebook separado para mostrar el poder de Python con los datos de texto.\n", + "\n", + "Pero antes de avanzar a eso, deberíamos presentarle las potentes ideas de **iteración** y **condicionales** en Python." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Iteración con `for`\n", + "\n", + "La idea de _iteración_ es básicamente repetir un proceso varias veces. Si tienes experiencia en programación con otro idioma (como C o Java, por ejemplo), puedes tener una idea de cómo crear iteraciones con sentencias `for`. Pero estos son un poco diferentes en Python, como puede leer en la [documentación](https://docs.python.org/3/tutorial/controlflow.html#for-statements).\n", + "\n", + "En Python, la instrucción `for` itera sobre los elementos de una secuencia. Digamos que se tiene una lista llamada `fruits` que contiene cadenas de texto con nombres de fruta. Puedes escribir una ciclo for de la siguiente forma:\n", + "\n", + "```Python\n", + "for fruit in fruits:\n", + "```\n", + "hacer algo con cada elemento de la lista.\n", + "\n", + "Aquí, por primera vez, encontraremos una característica distintiva del lenguaje Python: agrupanción por **indentación**. Para delimitar _qué_ Python debe hacer con cada `fruit` en la lista de` fruits`, colocamos las siguientes declaraciones _indentadas_ desde la izquierda.\n", + "\n", + "¿Cuánto indentar? Esta es una pregunta de estilo, y todos tienen una preferencia: dos espacios, cuatro espacios, una sola tabulación... todos son válidos: ¡lo importante es elegir un estilo y ser consecuente! De la misma manera, el código resulta más legible si escribirmos los nombres de las variables en inglés.\n", + "\n", + "Usemos cuatro espacios:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fruits = ['manzana', 'banana', 'naranja', 'cereza', 'mandarina']\n", + "\n", + "for fruit in fruits:\n", + " print(\"Come tu\", fruit)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##### Presta atención:\n", + "\n", + "* La instrucción `for` termina con dos puntos,`: `\n", + "* La variable `fruit` está implícitamente definida en la declaración` for`\n", + "* `fruit` tomará el valor de cada elemento de la lista` fruits`, en orden\n", + "* La sentencia indentada `print()` se ejecuta para cada valor de `fruit`\n", + "* Una vez que Python se queda sin frutas ('fruits'), se detiene\n", + "* ¡No necesitamos saber con anticipación cuántos elementos hay en la lista!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##### Pregunta desafiante:\n", + "\n", + "- ¿Cuál es el valor de la variable `fruit` después de ejecutar la instrucción` for` anterior? Discute con tu vecino. (Confirma tu conjetura en una celda de código)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Una función muy útil para usar con declaraciones `for` es **` enumerate () `**: agrega un contador que puede usar como índice mientras se ejecuta su iteración. Para usarlo, define implícitamente _dos_ variables en la instrucción `for`: el contador y el valor de la secuencia que se itera.\n", + "\n", + "Estudia el siguiente bloque de código:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "names = ['sam', 'zoe', 'naty', 'gil', 'tom']\n", + "\n", + "for i, name in enumerate(names):\n", + " names[i] = name.capitalize()\n", + "print(names)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##### Pregunta desafiante:\n", + "\n", + "- ¿Cuál es el valor de la variable `name` después de ejecutar la instrucción` for` anterior? Discute con tu vecino. (Confirma tu conjetura en una celda de código)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##### Ejercicio:\n", + "\n", + "Supongamos que tenemos una lista de listas (a.k.a., una _nested list_ o lista anidada), como se muestra a continuación:\n", + "```Python\n", + "fullnames = [['sam', 'jones'], \n", + " ['zoe', 'smith'], \n", + " ['joe', 'cheek'], \n", + " ['tom', 'perez']]\n", + "```\n", + "\n", + "Escriba un código que cree dos listas simples: una con los primeros nombres, otra con los apellidos de la lista anidada arriba, pero en mayúscula.\n", + "\n", + "Para comenzar, necesita crear dos listas _vacías_ utilizando los corchetes pero sin contenido. Hemos hecho eso para tí a continuación. _Pista_: ¡Usa el método de lista `append()`!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fullnames = [ ['sam','jones'], ['zoe','smith'],['joe','cheek'],['tom','perez'] ]\n", + "firstnames = []\n", + "lastnames = []\n", + "\n", + "# Write your code here" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Condicionales con declaraciones `if`\n", + "\n", + "Muchas veces necesitamos la habilidad de verificar condiciones y cambiar el comportamiento de nuestro programa dependiendo de la condición. Lo logramos con una instrucción `if`, que puede tomar una de tres formas." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "(1) **If**: Condicional \"si sucede algo\":" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "a = 8 \n", + "b = 3\n", + "\n", + "if a > b:\n", + " print('a es mayor que b')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "(2) **if-else**: Condicional \"si esto sino esto otro\": " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Definimos un número\n", + "x = 1547" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "if x % 17 == 0: \n", + " print('Tu numero es multiplo de 17.')\n", + "else:\n", + " print('Tu numero no es multiplo de 17.')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "*Nota:* El `%` representa una operación de módulo: da el resto de la división del primer argumento por el segundo" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "*Sugerencia:* Puedes descomentar la siguiente celda y aprender un buen truco para pedirle al usuario que inserte un número. Puedes usar esto en lugar de asignar un valor específico a `x`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#x = float(input('Insert your number: '))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "(3) **If-elif-else**: Multiples condicionales:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "a = 3\n", + "b = 5\n", + "\n", + "if a > b:\n", + " print('a es mayor a b')\n", + "elif a < b:\n", + " print('a es menor a b')\n", + "else:\n", + " print('a es igual a b')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "*Nota:* Podemos tener tantos condicionales del tipo `elif` como sea necesario." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##### Ejercicio\n", + "\n", + "Usando declaraciones `if`,` elif` y `else` escribe un código donde eliges un número de 4 dígitos, si es divisible entre 2 y 3, imprimes: 'Tu número no solo es divisible por 2 y 3 sino también por 6 '. Si es divisible por 2, imprime: 'Tu número es divisible por 2'. Si es divisible por 3, imprime: 'Tu número es divisible por 3'. Cualquier otra opción, imprime: 'Tu número no es divisible por 2, 3 o 6'" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Lo que hemos aprendido\n", + "\n", + "* Cómo usar el entorno de Jupyter y un notebook.\n", + "* Jugar con strings: acceder a valores, cortar (slicing) y métodos de strings.\n", + "* Jugar con listas: acceder a valores, cortar y enumerar métodos de listas.\n", + "* Iteración con declaraciones `for`.\n", + "* Condicionales con declaraciones `if`." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Referencias\n", + "\n", + "1. [Conceptos básicos del notebook: editor](http://jupyter-notebook.readthedocs.io/en/latest/examples/Notebook/Notebook%20Basics.html) (En inglés).\n", + "2. [\"Índices de puntos entre los elementos\"](https://blog.nelhage.com/2015/08/indices-point-between-elements/) publicación de blog de Nelson Elhage (2015, en inglés).\n", + "3. _Python para todos: explora datos usando Python 3_ (2016). Charles R. Severance. [PDF disponible](http://do1.dr-chuck.com/pythonlearn/EN_us/pythonlearn.pdf) (en inglés).\n", + "4. _Piense en Python: cómo pensar como un científico de la computación_ (2012). Allen Downey. Green Tea Press. [PDF disponible](http://greenteapress.com/thinkpython/thinkpython.pdf) (en inglés)." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Ejecuta esta celda para cargar el notebook con estilo, \n", + "# pero puedes ignorar su contenido.\n", + "from IPython.core.display import HTML\n", + "css_file = '../style/custom.css'\n", + "HTML(open(css_file, \"r\").read())" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.5.2" + }, + "widgets": { + "state": {}, + "version": "1.1.2" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/notebooks_es/3_Jugando_con_archivo_de_cursos.ipynb b/notebooks_es/3_Jugando_con_archivo_de_cursos.ipynb new file mode 100644 index 0000000..3cca43f --- /dev/null +++ b/notebooks_es/3_Jugando_con_archivo_de_cursos.ipynb @@ -0,0 +1,722 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "###### Contenido bajo licencia Creative Commons Attribution CC-BY 4.0, código bajo licencia BSD 3-Clause © 2017 L.A. Barba, N.C. Clementi" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Jugando con archivo de cursos\n", + "\n", + "Después de completar las lecciones [1 - Interactuando con Python](./1_Interactuando_con_Python.ipynb) y [2 - Strings y listas en acción](2_Strings_y_listas_en_accion.ipynb) de este curso _\"Cálculos Computacionales en ingeniería\"_, en este notebook se desarrolla un ejemplo práctico y completo usando todo lo que has aprendido.\n", + "\n", + "Quizás te preguntes por qué estamos dedicando las primeras lecciones del curso a jugar con strings y listas. _\"¡Ingeniería se trata de números, fórmulas y ecuaciones!\"_, puedes estar pensando. La razón es que este curso no asume ninguna experiencia de programación, por lo que buscamos que todos se acostumbren a Python, sin agregar la complejidad adicional de la utilización de números. La idea es familiarizarse primero con los reglas de la programación, aplicándolas a situaciones que no implican matemáticas... ¡al menos por ahora!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Jugando con el boletín MAE\n", + "\n", + "Vamos a jugar con el texto de un archivo que contiene una copia del [Boletín MAE](http://bulletin.gwu.edu/engineering-applied-science/mechanical-aerospace-engineering/#coursestext) para el año 2017-2018 (_Nota de la traducción: El Boletín MAE corresponde al detalle de los cursos dictados para Ingeniería Mecánica y Aeroespacial por la George Washington University, entre septiembre 2017 y agosto 2018_). Crearemos diferentes listas para ubicar el título, los créditos y la descripción de un curso en función del código del curso.\n", + "\n", + "El archivo de datos para este ejemplo se encuentra en una carpeta llamada `data`, que puedes encontrar en un nivel superior a la ubicación de esta lección, si has copiado los materiales del curso tal como fueron almacenados. Si tienes los datos en otro lugar, deberás editar tu mismo la ruta según la ubicación correcta para este archivo.\n", + "\n", + "Comenzaremos leyendo el archivo de datos en el notebook de Jupyter, luego limpiaremos un poco los datos y finalmente interactuaremos con sus datos de varias maneras." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Leer datos de un archivo\n", + "\n", + "Nos gustaría leer el contenido de este archivo en el notebook de Jupyter. Por lo general, es una buena idea echar un vistazo primero al archivo, para ver cómo se ve su contenido. Esto también nos da la oportunidad de enseñarte un truco que te será muy útil.\n", + "\n", + "¿Recuerdas que las celdas de código en un notebook pueden manejar cualquier declaración válida de **IPython**?. Bueno, IPython es capaz de hacer algo más que sólo Python: también puede ejecutar cualquier [comando del sistema](https://ipython.org/ipython-doc/3/interactive/reference.html#system-shell-access). Si conoces un poco de Unix, esto te será muy útil; por ejemplo, podrías enumerar todos los archivos en el directorio de trabajo.\n", + "\n", + "Para ejecutar un comando de sistema (o comando de la shell), antepone `!` -un \"bang\" o signo de exclamación. El comando que necesitamos es `head`, que imprime las primeras líneas de un archivo.\n", + "\n", + "Nuestra carpeta de datos se encuentra en un directorio superior al de los notebooks: en Unix, ir a un directorio superior se obtiene con 2 puntos seguidos ('..'). Así que necesitamos tener `../ data/` antes del nombre del archivo, `mae_bulletin.txt`, como parte de la ruta.\n", + "\n", + "Como ya se indicó, el comando `head` (que no es de python) puede utilizarse si se coloca antes un signo de exclamación:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "!head ../data/mae_bulletin.txt" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "¡Se ve bien! El siguiente paso es abrir el archivo y guardar sus contenidos en una variable de Python que podamos usar.\n", + "\n", + "La función **`open()`** se utiliza con el nombre del archivo indicado como un argumento _string_ (tenga en cuenta las comillas) y devuelve un objeto de archivo Python. Tenemos varias opciones posibles, y definitivamente es recomandable que leas la [documentación](https://docs.python.org/2/tutorial/inputoutput.html#reading-and-writing-files) sobre cómo leer y escribir archivos. Sin embargo, describiremos las principales opciones:\n", + "\n", + "**Método read**\n", + "\n", + "Si usas el método de archivo **`read()`**, obtendrás un único string (cadena de texto) con todos los contenidos del archivo. Este string tendrá todas las líneas, con los saltos de líneas indicadas por el carácter `\\n`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mae_bulletin_file = open('../data/mae_bulletin.txt')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mae_bulletin_text = mae_bulletin_file.read()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "type(mae_bulletin_text)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "len(mae_bulletin_text)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(mae_bulletin_text)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Método list**\n", + "\n", + "Otra opción es usar la función **`list()`** para crear una lista de líneas a partir del contenido del archivo." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mae_bulletin_file = open('../data/mae_bulletin.txt')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mae_bulletin_text = list(mae_bulletin_file)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "type(mae_bulletin_text)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "len(mae_bulletin_text)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(mae_bulletin_text)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Método readlines**\n", + "\n", + "Lo más común es utilizar el método **`readlines()`**, con lo cual obtendrás una lista, donde cada elemento de esta lista es una string con una de las línea del archivo. El orden de la lista corresponde al orden de las líneas en el archivo como es esperable. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mae_bulletin_file = open('../data/mae_bulletin.txt')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mae_bulletin_text = mae_bulletin_file.readlines()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "type(mae_bulletin_text)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "len(mae_bulletin_text)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(mae_bulletin_text)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Limpieza y organización de datos de texto\n", + "\n", + "Al manipular datos de texto, una de las acciones más comunes es deshacerse de líneas innecesarias y espacios en blanco. En nuestro caso, eliminaremos los espacios al principio y al final de cada línea.\n", + "\n", + "Ten en cuenta que también hay algunas líneas en blanco, que omitiremos. El objetivo es obtener dos listas nuevas: una con la identificación de cada curso y otra con la descripción de cada curso.\n", + "\n", + "Considera el siguiente código:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "courses = []\n", + "descriptions = []\n", + "\n", + "for line in mae_bulletin_text:\n", + " line = line.strip() #Eliminar los espacios en blanco\n", + " if line == '': #Saltarse las lineas en blanco \n", + " continue\n", + " elif line.startswith('MAE'): \n", + " courses.append(line) #Guardar las lineas que comienzan con MAE en la lista de cursos\n", + " else:\n", + " descriptions.append(line) #Guardar las líneas que NO comienzan con MAE en la lista de descripciones" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Asegúrate de visitar la [documentación](https://docs.python.org/3/library/stdtypes.html#string-methods) para conocer los métodos de strings y tener una idea de todas las cosas que pueden hacerse con Python. Aquí, usamos el método **`strip()`** para deshacernos de los espacios iniciales y finales, y también usamos **`startswith()`** para saber si el string correspondía al código de un curso.\n", + "\n", + "Para verificar lo que hemos obtenido, sólo es necesario imprimir algunos elementos de cada lista:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#imprimir los primeros 5 elementos\n", + "print(courses[0:5])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#imprmir los primeros 3 elementosde las descripciones\n", + "print(descriptions[0:3])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "¡También deberíamos verificar que ambas listas tengan la misma longitud!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(len(courses))\n", + "print(len(descriptions))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Separa la lista de cursos en la identificación del curso, título y créditos\n", + "\n", + "La lista `course` contiene strings con la información del código del curso, su título y cantidad de créditos, resultaría conveniente tener por separado. Una forma posible es la siguiente:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "course_id = []\n", + "course_title = []\n", + "course_credits = []\n", + "\n", + "for course in courses:\n", + " course_info = course.split('. ') \n", + " course_id.append(course_info[0])\n", + " course_title.append(course_info[1])\n", + " course_credits.append(course_info[2])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Ten en cuenta que dividimos la información del curso utilizando el string `'. '` (punto + espacio) para evitar tener un espacio en blanco adicional al comienzo de cada cadena en las listas de títulos y créditos del curso. Otra forma de conseguir lo mismo sería dividir con sólo el punto y después utilizar `strip`.\n", + "\n", + "Imprimamos los primeros elementos de las nuevas listas." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(course_id[0:5])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(course_title[0:5])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(course_credits[0:5])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Información del curso de seguimiento\n", + "\n", + "Las listas que hemos creado están alineadas: cada elemento en la misma ubicación de índice corresponde al mismo curso. Al encontrar la ubicación (el índice) de un identificador de curso, podemos acceder a toda la otra información.\n", + "\n", + "Usamos el método `index()` para encontrar el índice de un identificador de curso y rastrear el resto de la información. ¡Inténtalo!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "course_id.index('MAE 3190')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "n = course_id.index('MAE 3190')\n", + "print(course_id[n])\n", + "print(course_title[n])\n", + "print(course_credits[n])\n", + "print(descriptions[n])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### ¿Cuántos cursos tienen prerrequisitos?\n", + "\n", + "Exploremos una nueva idea: podemos buscar todos los cursos que tengan requisitos previos usando una declaración `for`. En este caso, iteraremos sobre los _indices_ de los elementos en la lista `descriptions`.\n", + "\n", + "Esto nos da la oportunidad de presentar un objeto de Python muy útil: **`range`**: crea una secuencia de números en la progresión aritmética que permite iterar. Con un único argumento, `range(N)` creará una secuencia de longitud `N` comenzando en cero:` 0, 1, 2, ..., N-1`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for i in range(4):\n", + " print(i)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Un detalle interesante del método `range` es que se crea sobre la marcha, al iterar sobre él. No es realmente una lista, aunque para la mayoría de los propósitos prácticos se comportará como una lista.\n", + "\n", + "Una forma típica de usarlo es con un argumento que sale de la función `len ()`. \n", + "\n", + "Observa el siguiente bloque de código:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "course_with_pre = []\n", + "\n", + "for i in range(len(descriptions)): #La variable i tomará los valores 0, 1, ..., 318\n", + " if 'Prerequisite' in descriptions[i]: #Se verá si el elemento i-esimo de la lista contiene 'Prerequisite'\n", + " course_with_pre.append(course_id[i]) #Se almacenará en la lista si se cumple el condicional" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Ahora tenemos una lista llamada `course_with_pre` que contiene el identificador de curso de todos los cursos que tienen requisitos previos." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(course_with_pre)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##### Ejercicio:\n", + "\n", + "1. Guarda en una nueva lista llamada `course_with_cor` todos los cursos que tengan un correquisito e imprime la lista.\n", + "2. Utilizando una declaración `for` y declaraciones` if-elif-else`, separa los cursos que se ofrecen en el semestre de otoño, los ofrecidos en el semestre de primavera, los que se ofrecen en ambos semestres y los que no especifican un semestre. Crea 4 listas: `fall_and_spring`,` fall`, `spring` y` not_spec`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#Anota tu respuesta acá\n", + "course_with_cor = []\n", + "fall_and_spring = []\n", + "fall = []\n", + "not_spec = []" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Para comprobar tus respuestas, elimine los comentarios de las siguientes líneas eliminando el símbolo # y ejecutando la celda. La ejecución de la celda no arroja errores, ¡lo hiciste bien!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#course_with_cor_ans = ['MAE 3184', 'MAE 4183', 'MAE 4195', 'MAE 6194', 'MAE 6195']\n", + "#fall_and_spring_ans = []\n", + "#fall_ans = ['MAE 1004', 'MAE 2117', 'MAE 3126', 'MAE 3145', 'MAE 3162', 'MAE 3166W', 'MAE 3190', 'MAE 3191', 'MAE 4157', 'MAE 4163', 'MAE 4193', 'MAE 4199', 'MAE 6210', 'MAE 6275']\n", + "#spring_ans = ['MAE 3128', 'MAE 3167W', 'MAE 3193', 'MAE 6194', 'MAE 6195', 'MAE 6229', 'MAE 6235', 'MAE 6242', 'MAE 6247', 'MAE 6249', 'MAE 6258']\n", + "#not_spec_ans = ['MAE 2124', 'MAE 2131', 'MAE 2170', 'MAE 3120', 'MAE 3134', 'MAE 3155', 'MAE 3171', 'MAE 3184', 'MAE 3187', 'MAE 3192', 'MAE 3195', 'MAE 3196', 'MAE 3197', 'MAE 4129', 'MAE 4149', 'MAE 4168', 'MAE 4172', 'MAE 4182', 'MAE 4183', 'MAE 4194', 'MAE 4195', 'MAE 4198', 'MAE 6201', 'MAE 6203', 'MAE 6204', 'MAE 6207', 'MAE 6220', 'MAE 6221', 'MAE 6222', 'MAE 6223', 'MAE 6224', 'MAE 6225', 'MAE 6226', 'MAE 6227', 'MAE 6228', 'MAE 6230', 'MAE 6231', 'MAE 6232', 'MAE 6233', 'MAE 6234', 'MAE 6237', 'MAE 6238', 'MAE 6239', 'MAE 6240', 'MAE 6241', 'MAE 6243', 'MAE 6244', 'MAE 6245', 'MAE 6246', 'MAE 6251', 'MAE 6252', 'MAE 6253', 'MAE 6254', 'MAE 6255', 'MAE 6257', 'MAE 6260', 'MAE 6261', 'MAE 6262', 'MAE 6263', 'MAE 6270', 'MAE 6271', 'MAE 6274', 'MAE 6276', 'MAE 6277', 'MAE 6280', 'MAE 6281', 'MAE 6282', 'MAE 6283', 'MAE 6284', 'MAE 6286', 'MAE 6287', 'MAE 6288', 'MAE 6290', 'MAE 6291', 'MAE 6292', 'MAE 6298', 'MAE 6998', 'MAE 6999', 'MAE 8350', 'MAE 8351', 'MAE 8352', 'MAE 8998', 'MAE 8999']\n", + "\n", + "#assert course_with_cor == course_with_cor_ans\n", + "#assert fall_and_spring == fall_and_spring_ans \n", + "#assert fall == fall_ans\n", + "#assert spring == spring_ans\n", + "#assert not_spec == not_spec_ans" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Lo que hemos aprendido\n", + "\n", + "* Los comandos del sistema en una celda de código comienzan con un bang o exclamación (`!`).\n", + "* Abrir un archivo de texto y guardar su contenido en un string o una lista de strings.\n", + "* Limpiar datos de texto usando métodos de cadena.\n", + "* Manipular texto en listas." + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 34, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Ejecuta esta celda para cargar el notebook con estilo, \n", + "# pero puedes ignorar su contenido.\n", + "from IPython.core.display import HTML\n", + "css_file = '../style/custom.css'\n", + "HTML(open(css_file, \"r\").read())" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.5.2" + }, + "widgets": { + "state": {}, + "version": "1.1.2" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/notebooks_es/4_Conociendo_arrays_y_graficos.ipynb b/notebooks_es/4_Conociendo_arrays_y_graficos.ipynb new file mode 100644 index 0000000..59b6ae4 --- /dev/null +++ b/notebooks_es/4_Conociendo_arrays_y_graficos.ipynb @@ -0,0 +1,1194 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "###### Contenido bajo licencia Creative Commons Attribution CC-BY 4.0, código bajo licencia BSD 3-Clause © 2017 L.A. Barba, N.C. Clementi" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Conociendo arrays y gráficos\n", + "\n", + "Bienvenido a la **Lección 4** del primer módulo del curso _\"Cálculos Computacionales en ingeniería\"_. ¡Ya has recorrido un largo camino!\n", + "\n", + "Recuerda, este curso no asume ninguna experiencia de programación por lo que las tres primeras lecciones se centraron en crear una base con construcciones de programación de Python sin utilizar Matemáticas. Las lecciones anteriores son:\n", + "\n", + "* [Lección 1](./1_Interactuando_con_Python.ipynb): Interactuando con Python\n", + "* [Lección 2](./2_Strings_y_listas_en_accion.ipynb): String y listas en acción.\n", + "* [Lección 3](./3_Jugando_con_archivo_de_cursos.ipynb): Jugando con archivo de cursos.\n", + "\n", + "En la mayoría de las necesidades informáticas en ingeniería es conveniente el uso de *arrays*: secuencias de datos del mismo tipo. Se comportan como listas, a excepción de la restricción en el tipo de sus elementos. Hay una gran ventaja de eficiencia cuando sabes que todos los elementos de una secuencia son del mismo tipo, por lo que los métodos equivalentes de arrays se ejecutan mucho más rápido que los de las listas (*Nota de la traducción*: arrays y matrices son distintos tipos en python, por lo que se utilizará la palabra arrays sin traducirla).\n", + "\n", + "El lenguaje Python se extiende con la utilización de **librerías** o bibliotecas. La librería más importante en ciencia e ingeniería es **NumPy**, que proporciona la estructura de datos _array n-dimensional_ (llamado `ndarray`) y una gran cantidad de funciones, operaciones y algoritmos para cálculos de álgebra lineal extremadamente eficientes.\n", + "\n", + "En esta lección, comenzarás a jugar con arrays de NumPy y descubrirás su poder. También se encontrará con la librería **Matplotlib**, muy apreciada para crear gráficos bidimensionales de datos." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Importando librerías\n", + "\n", + "Primero, algunos consejos sobre al importar librerías para expandir Python. Debido a que las librerías son grandes colecciones de código y son para fines especiales, no se cargan automáticamente al iniciar Python (o IPython, o Jupyter). Tienes que importar una librería usando el comando `import`. Por ejemplo, para importar **NumPy** y recibir todos los beneficios del álgebra lineal, ingresamos:\n", + "\n", + "```python\n", + "import numpy\n", + "```\n", + "\n", + "Una vez que se ejecuta ese comando en una celda de código, puedes llamar a cualquier función de NumPy usando la notación de puntos, anteponiendo el nombre de la librería. Por ejemplo, algunas funciones comúnmente usadas son:\n", + "\n", + "* [`numpy.linspace()`](https://docs.scipy.org/doc/numpy/reference/generated/numpy.linspace.html)\n", + "* [`numpy.ones()`](https://docs.scipy.org/doc/numpy/reference/generated/numpy.ones.html#numpy.ones)\n", + "* [`numpy.zeros()`](https://docs.scipy.org/doc/numpy/reference/generated/numpy.zeros.html#numpy.zeros)\n", + "* [`numpy.empty()`](https://docs.scipy.org/doc/numpy/reference/generated/numpy.empty.html#numpy.empty)\n", + "* [`numpy.copy()`](https://docs.scipy.org/doc/numpy/reference/generated/numpy.copy.html#numpy.copy)\n", + "\n", + "Los enlaces anteriores te llevarán a la documentación de estas útiles funciones de NumPy." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##### Advertencia:\n", + "\n", + "Encontrará gran variedad de código en internet con distintas sintaxis para importar librerías. Algunos usarán:\n", + "```python\n", + "import numpy como np\n", + "```\n", + "\n", + "Lo anterior crea un alias para `numpy` con la cadena más corta `np`, por lo que llamaría a una función **NumPy** de esta manera: `np.linspace()`. Esta es sólo una forma alternativa de hacerlo, para personas que les resulta demasiado largo escribir `numpy` y quieren evitar escribir 3 caracteres cada vez. En estos notebooks escribiremos `numpy` porque nos parece más legible y hermoso. Por lo tanto, usaremos simplemente:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Creando arrays\n", + "\n", + "Para crear un array de NumPy a partir de una lista existente de números homogéneos, llamamos **`numpy.array ()`**, así:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "numpy.array([3, 5, 8, 17])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "NumPy ofrece muchas [formas de crear arrays](https://docs.scipy.org/doc/numpy/reference/routines.array-creation.html#routines-array-creation) además de lo anterior. Ya hemos mencionado algunos de ellos anteriomente en el notebook.\n", + "\n", + "Juega con `numpy.ones ()` y `numpy.zeros ()`: estas funciones permiten crear arrays llenos de unos y ceros, respectivamente. Pasamos como argumento la cantidad de elementos del array que queremos obtener." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "numpy.ones(5)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "numpy.zeros(3)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Otra función útil: `numpy.arange ()`, nos regresa un array de valores espaciados uniformemente en un intervalo definido. Es el equivalente de la función range pero en su versión rápida de Numpy.\n", + "\n", + "*Sintaxis:*\n", + "\n", + "`numpy.arange(start, end, step)`\n", + "\n", + "donde `start` (inicio) por defecto es cero, `stop` (fin) no se incluye, y el valor predeterminado\n", + "para `step` (el paso) es 1. ¡Te aconsejamos jugar con algunos valores para acostumbrarte!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "numpy.arange(4)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "numpy.arange(2, 6)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "numpy.arange(2, 6, 2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "numpy.arange(2, 6, 0.5)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "La funcion `numpy.linspace()` es similar a `numpy.arange()`, pero permite que digas el número de elementos a obtener en lugar del un tamaño de paso. Devuelve un array con números espaciados uniformemente durante el intervalo especificado.\n", + "\n", + "*Sintaxis:*\n", + "\n", + "`numpy.linspace(start, stop, num)`\n", + "\n", + "`stop` está incluido por defecto (se puede eliminar, como indica la documentación), y ` num` de forma predeterminada es 50." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "numpy.linspace(2.0, 3.0)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "len(numpy.linspace(2.0, 3.0))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "numpy.linspace(2.0, 3.0, 6)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "numpy.linspace(-1, 1, 9)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Operaciones de arrays\n", + "\n", + "Creemos algunas variables de tipo array para poder realizar algunas operaciones con ellos." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "x_array = numpy.linspace(-1, 1, 9)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "collapsed": true + }, + "source": [ + "Ahora que lo hemos guardado como una variable, podemos hacer algunos cálculos con el array. Por ejemplo, aplicar el cuadrado a cada elemento del array (¡de una sola vez!):" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "y_array = x_array**2\n", + "print(y_array)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "También podemos tomar la raíz cuadrada de un array de valores positivos, usando la función `numpy.sqrt()`:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "z_array = numpy.sqrt(y_array)\n", + "print(z_array)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Ahora que tenemos dos arrays diferentes `x_array`, ` y_array` y `z_array`, podemos hacer más cálculos, como sumarlos o multiplicarlos. Por ejemplo:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "add_array = x_array + y_array \n", + "print(add_array)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "La adición de arrays se define elemento a elemento (en inglés, esto se dice element-wise). La multiplicación de arrays también se realiza elemento a elemento:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mult_array = x_array * z_array\n", + "print(mult_array)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "También podemos dividir arrays, pero debes tener cuidado de no dividir por cero. Esta operación dará como resultado **`nan`** que significa *Not a Number* (No un Número). Python todavía realizará la división, pero nos contará sobre el problema.\n", + "\n", + "Veamos cómo se vería esa situación:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "x_array / y_array" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Arrays multidimensionales\n", + "\n", + "### Arrays 2D\n", + "\n", + "NumPy puede crear arrays de N dimensiones. Por ejemplo, un array 2D es como una matriz de Matemática, y se crea a partir de una lista anidada de la siguiente manera:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "array_2d = numpy.array([[1, 2], [3, 4]])\n", + "print(array_2d)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Los arrays 2D se pueden sumar, restar y multiplicar:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "X = numpy.array([[1, 2], [3, 4]])\n", + "Y = numpy.array([[1, -1], [0, 1]])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "La adición de estos dos arrays funciona exactamente como era de esperar:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "X + Y" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "¿Qué pasa si tratamos de multiplicar arrays utilizando el operador `'*'`?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "X * Y" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "La multiplicación usando el operador `'*'` es elemento a elemento. Si queremos hacer una multiplicación matricial usamos el operador `'@'`:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "X @ Y" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "O de manera equivalente, podemos usar `numpy.dot ()`:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "numpy.dot(X, Y)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Arrays 3D\n", + "\n", + "Vamos a crear un array 3D a partir de un array 1D. Podemos usar [`numpy.reshape()`](https://docs.scipy.org/doc/numpy/reference/generated/numpy.reshape.html), donde pasamos el array que queremos reacomodar y la forma queremos obtener, es decir, la cantidad de elementos en cada dimensión.\n", + "\n", + "*Sintaxis*\n", + " \n", + "`numpy.reshape(array, newshape)`\n", + "\n", + "Por ejemplo:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "a = numpy.arange(24)\n", + "print(a)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "a_3D = numpy.reshape(a, (2, 3, 4))\n", + "print(a_3D)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Podemos verificar la forma de un array de NumPy usando la función `numpy.shape ()`:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "numpy.shape(a_3D)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Visualizar las dimensiones del array `a_3D` puede ser complicado, así que proporcionamos un diagrama que lo ayudará a comprender cómo se asignan las dimensiones. Cada dimensión se muestra como un eje de coordenadas. Para un array 3D, en el \"eje x\", tenemos los sub-array que son bidimensionales. Tenemos dos de estos sub-array 2D, en este caso; cada uno tiene 3 filas y 4 columnas. Estudie este boceto cuidadosamente, mientras compara con la forma en que se imprime el array `a_3D`.\n", + "\n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "collapsed": true + }, + "source": [ + "Cuando tenemos arrays multidimensionales, podemos acceder a secciones de sus elementos realizando slicing en cada dimensión. Esta es una de las ventajas del uso de arrays; no podemos hacer esto con listas.\n", + "\n", + "Accedamos a algunos elementos del array 2D que llamamos `X`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "X" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Tomar el primer elemento en la primera fila y la primera columna\n", + "X[0, 0]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Tomar el elemento de la primera fila y segunda columna\n", + "X[0, 1]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##### Ejercicios:\n", + "\n", + "Del array X:\n", + "\n", + "1. Coge el segundo elemento en la primera columna.\n", + "2. Coge el segundo elemento en la segunda columna." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Juega con algunos cortes (slicing) de este array:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Tomar la primera columna\n", + "X[:, 0]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Cuando no especificamos el punto inicial y/o final en el slicing, el símbolo `':'` significa \"todo\". En el ejemplo anterior, le estamos diciendo a NumPy que queremos todos los elementos del índice 0 en la segunda dimensión (la primera columna)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Tomar la primera fila\n", + "X[0, :]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##### Ejercicios:\n", + "\n", + "Del array X:\n", + "\n", + "1. Coge la segunda columna.\n", + "2. Coge la segunda fila." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Practiquemos con el array 3D." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "a_3D" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Si queremos tomar la primera columna de los arrays bidimensionales de nuestro array `a_3D`, debemos hacer:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "a_3D[:, :, 0]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "La línea de arriba le está diciendo a NumPy:\n", + "\n", + "* El primer `':'`: en la primera dimensión queremos tomar todos los elementos (2 arrays).\n", + "* El segundo `':'`: desde la segunda dimensión queremos tomar todos los elementos (todas las filas).\n", + "* El `'0'`: desde la tercera dimensión queremos tomar el primer elemento (primera columna).\n", + "\n", + "Si queremos los primeros 2 elementos de la primera columna de ambos arrays:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "a_3D[:, 0:2, 0]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "A continuación, desde el primer array bidimensional de nuestro array `a_3D`, tomaremos los dos elementos intermedios de la segunda fila:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "a_3D[0, 1, 1:3]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##### Ejercicios:\n", + "\n", + "Del array llamada `a_3D`:\n", + "\n", + "1. Toma los dos elementos del medio (es decir, 17 y 18) del segundo array.\n", + "2. Coge la última fila de ambos arrays.\n", + "3. Tome los elementos del primer array bidimensional que excluyen la primera fila y la primera columna.\n", + "4. Tome los elementos del segundo array bidimensional que excluyen la última fila y la última columna." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## NumPy es rápido y limpio\n", + "\n", + "Cuando trabajamos con números, los arrays son la mejor opción porque la librería NumPy tiene funciones que están optimizadas y, por lo tanto, son más rápidas que las de Python. Esto es especialmente cierto si tenemos arrays grandes. Además, usar arrays de NumPy y sus propiedades hace que nuestro código sea más legible.\n", + "\n", + "Por ejemplo, si quisiéramos sumar 2 listas de python elemento a elemento, necesitaríamos hacerlo con una declaración `for`. Si queremos agregar dos arrays de NumPy, simplemente usamos el símbolo de suma `'+'`.\n", + "\n", + "Para ilustrar lo anterior, sumaremos dos listas y dos arrays (con elementos aleatorios) y compararemos el tiempo que requiere cada suma." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Suma de elementos de una lista de Python\n", + "\n", + "Usando la librería de Python [`random`](https://docs.python.org/3/library/random.html) generaremos dos listas con 100 elementos pseudoaleatorios en el rango [0,100), sin números repetido." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#Importar la librería random\n", + "import random" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#Generar 2 listas de enteros con 100 elementos\n", + "lst_1 = random.sample(range(100), 100)\n", + "lst_2 = random.sample(range(100), 100)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#Imprimir los primeros 10 elementos\n", + "print(lst_1[0:10])\n", + "print(lst_2[0:10])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Verificar el tipo de las variables\n", + "print(type(lst_1))\n", + "print(type(lst_2))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Necesitamos escribir una declaración `for`, añadiendo el resultado de la suma de elementos a una nueva lista que llamamos `result_lst`.\n", + "\n", + "Para contabilizar el tiempo, podemos usar el comando \"mágico\" de IPython `%% time`. Escribiendo al comienzo de la celda de código, el comando `%%time` nos dará el tiempo que lleva ejecutar todo el código en esa celda." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%time\n", + "res_lst = []\n", + "for i in range(100):\n", + " res_lst.append(lst_1[i] + lst_2[i])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(res_lst[0:10])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Suma de arrays en NumPy\n", + "\n", + "En este caso, generamos arrays con enteros aleatorios usando una función especial de NumPy: [`numpy.random.randint ()`](https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy. random.randint.html). Los arrays que generamos con esta función no serán como las listas: en este caso, tendremos 100 elementos en el rango [0, 100) pero pueden repetirse.\n", + "\n", + "Nuestro objetivo es comparar el tiempo que lleva calcular la suma de los elementos de una lista, de modo que todo lo que importa es que los arrays y las listas son de la misma longitud y tipo (enteros)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "arr_1 = numpy.random.randint(0, 100, size=100)\n", + "arr_2 = numpy.random.randint(0, 100, size=100)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#print first 10 elements\n", + "print(arr_1[0:10])\n", + "print(arr_2[0:10])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Verificar el tipo de las variables\n", + "print(type(arr_1))\n", + "print(type(arr_2))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Ahora podemos usar la magia de la celda `%% time`, nuevamente, para ver cuánto tarda NumPy en calcular la suma de elementos." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%time\n", + "arr_res = arr_1 + arr_2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Ten en cuenta que en el caso de los arrays, el código no solo es más legible (sólo una línea de código), sino que también es más rápido que con las listas. Esta vez, la ventaja será mayor con arrays y listas más grandes.\n", + "\n", + "Tus mediciones de tiempo pueden variar a los que mostramos en este notebook, porque estará calculándolos en una máquina diferente." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##### Ejercicio\n", + "\n", + "1. Repite la comparación entre listas y arrays, usando arrays más grandes; por ejemplo de tamaño 10,000.\n", + "2. Repite el análisis, pero ahora en lugar de sumar realiza la operación que eleva cada elemento de un array/lista a la potencia dos. Usa arrays de 10,000 elementos." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Tiempo de Graficar\n", + "\n", + "¡Te encantará la librería **Matplotlib**! Aprenderás a continuación sobre el módulo `pyplot`, que hace gráficos de líneas.\n", + "\n", + "Necesitamos algunos datos para graficar. Definiramos un array NumPy, para luego calcular su cuadrado, cubo y raíz cuadrada, elemento a elemento. Graficaremos estos valores con el array original en el eje x." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#Crear el array base\n", + "xarray = numpy.linspace(0, 2, 41)\n", + "print(xarray)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#Generar los arrays a graficar\n", + "pow2 = xarray**2\n", + "pow3 = xarray**3\n", + "pow_half = numpy.sqrt(xarray)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Para graficar los arrays resultantes como una función de la original (`xarray`) en el eje x, necesitamos importar el módulo `pyplot` de **Matplotlib**." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from matplotlib import pyplot\n", + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "El comando `%matplotlib inline` permite obtener nuestros gráficos dentro del notebook (en lugar de una ventana emergente, que es el comportamiento predeterminado de `pyplot` para jupyter).\n", + "\n", + "Utilizaremos la función `pyplot.plot()`, especificando el color de línea (`'k'` para negro) y el estilo de línea (`' -'`, `'-'` y `':'` para línea continua, punteada y punteada), y dando a cada línea una etiqueta. Tenga en cuenta que los valores para `color` (color),` linestyle` (tipo de línea) y `label` (etiqueta) deben darse entre comillas." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#Plot x^2\n", + "pyplot.plot(xarray, pow2, color='k', linestyle='-', label='square')\n", + "#Plot x^3\n", + "pyplot.plot(xarray, pow3, color='k', linestyle='--', label='cube')\n", + "#Plot sqrt(x)\n", + "pyplot.plot(xarray, pow_half, color='k', linestyle=':', label='square root')\n", + "#Plot the legends in the best location\n", + "pyplot.legend(loc='best')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Para ilustrar otras características de Matplotlib, trazaremos los mismos datos, pero variando los colores en lugar del estilo de línea. También usaremos la sintaxis LaTeX para escribir fórmulas en las etiquetas. Si deseas obtener más información sobre la sintaxis de LaTeX, hay una [guía rápida de LaTeX, en inglés](https://users.dickinson.edu/~richesod/latex/latexcheatsheet.pdf) disponible en línea.\n", + "\n", + "Agregar un punto y coma (`';'`) a la última línea del bloque de código de trazado evitar que se imprima `` junto al gráfico." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#Plot x^2\n", + "pyplot.plot(xarray, pow2, color='red', linestyle='-', label='$x^2$')\n", + "#Plot x^3\n", + "pyplot.plot(xarray, pow3, color='green', linestyle='-', label='$x^3$')\n", + "#Plot sqrt(x)\n", + "pyplot.plot(xarray, pow_half, color='blue', linestyle='-', label='$\\sqrt{x}$')\n", + "#Plot the legends in the best location\n", + "pyplot.legend(loc='best'); " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "¿No es increíble? Esperamos que ahora estés imaginando todo lo que puedes hacer con los notebooks de Jupyter, Python y sus librerías científicas **NumPy** y **Matplotlib**. \n", + "\n", + "Acabamos de realizar una introducción a los gráficos, pero seguiremos aprendiendo sobre el poder de **Matplotlib** en la próxima lección.\n", + "\n", + "Si tienes curiosidad, puedes explorar muchos gráficos increíbles en la [galería de ejemplos de Matplotlib](http://matplotlib.org/gallery.html)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##### Ejercicio:\n", + "\n", + "Elige dos operaciones diferentes para aplicar a `xarray` y realiza la operación de manera directa en el mismo gráfico." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Lo que hemos aprendido\n", + "\n", + "* Cómo importar librerías\n", + "* Arrays multidimensionales usando NumPy\n", + "* Acceder a valores y slicing en arrays de NumPy\n", + "* Usar `%%time` para cronometrar la ejecución de la celda.\n", + "* Comparar rendimientos: listas versus arrays\n", + "* Grafico básico con `pyplot` de Matplotlib." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Referencias\n", + "\n", + "1. _Effective Computation in Physics: Field Guide to Research with Python_ (Computación efectiva en Física, Guía práctica para investigación con Python, 2015). Anthony Scopatz & Kathryn D. Huff. O'Reilly Media, Inc.\n", + "\n", + "2. _Numerical Python: A Practical Techniques Approach for Industry_. (Python Numérico: Técnicas Prácticas para la Industria, 2015). Robert Johansson. Appress. \n", + "\n", + "2. [\"The world of Jupyter\"—a tutorial](https://github.com/barbagroup/jupyter-tutorial) (El mundo de Jupyter-un tutorial, 2016). Lorena A. Barba." + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 54, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Ejecuta esta celda para cargar el notebook con estilo, \n", + "# pero puedes ignorar su contenido.\n", + "from IPython.core.display import HTML\n", + "css_file = '../style/custom.css'\n", + "HTML(open(css_file, \"r\").read())" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.5.2" + }, + "widgets": { + "state": {}, + "version": "1.1.2" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/notebooks_es/5_Regresion_Lineal_con_datos_reales.ipynb b/notebooks_es/5_Regresion_Lineal_con_datos_reales.ipynb new file mode 100644 index 0000000..5785b73 --- /dev/null +++ b/notebooks_es/5_Regresion_Lineal_con_datos_reales.ipynb @@ -0,0 +1,1042 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "###### Contenido bajo licencia Creative Commons Attribution CC-BY 4.0, código bajo licencia BSD 3-Clause © 2017 L.A. Barba, N.C. Clementi" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Regresión lineal con datos reales\n", + "\n", + "## La temperatura de la tierra variando en el tiempo\n", + "\n", + "En esta lección, aplicaremos todo lo que hemos aprendido (y más) para analizar datos reales de la temperatura de la Tierra a lo largo del tiempo.\n", + "\n", + "¿Está aumentando la temperatura global? ¿Cuánto? ¡Esta es una cuestión de gran importancia en el mundo de hoy!\n", + "\n", + "Los datos sobre las temperaturas globales están disponibles en varias fuentes: NASA, el Centro Nacional de Datos Climáticos (NCDC) y la Universidad de East Anglia en el Reino Unido. Consulta la [Corporación Universitaria de Investigación Atmosférica](https://www2.ucar.edu/climate/faq/how-much-has-global-temperature-risen-last-100-years) (UCAR) para un discusión profunda.\n", + "\n", + "El [Centro Goddard de Vuelos Espaciales de la NASA](http://svs.gsfc.nasa.gov/goto?3901) es una de estas fuentes de datos climáticos globales. Ellos produjeron el siguiente video que muestra un mapa de colores de las cambiantes **anomalías de temperatura de la superficie** de 1880 a 2015.\n", + "\n", + "El término [anomalía de temperatura global](https://www.ncdc.noaa.gov/monitoring-references/faq/anomalies.php) se aplica a la diferencia de temperatura con respecto a un valor de referencia o un promedio a largo plazo. Es una forma muy útil de ver el problema y, en muchos sentidos, mejor que la temperatura absoluta. Por ejemplo, un mes de invierno puede ser más frío que el promedio en Washington DC, y también en Miami, pero las temperaturas absolutas serán diferentes en ambos lugares." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from IPython.display import YouTubeVideo\n", + "YouTubeVideo('gGOzHVUQCw0')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "¿Cómo podríamos entender las _tendencias_ de los datos de la temperatura global?\n", + "\n", + "El primer paso para analizar datos desconocidos es generar algunos gráficos simples utilizando **Matplotlib**. Vamos a ver el historial de anomalías de temperatura, contenido en un archivo, y hacemos nuestro primer diagrama para explorar estos datos.\n", + "\n", + "Vamos a suavizar los datos y luego ajustaremos una línea para encontrar una tendencia, graficando para ver cómo se ve todo.\n", + "\n", + "¡Empecemos!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Paso 1: leyendo un archivo de datos\n", + "\n", + "Tomamos los datos de la página web [NOAA](https://www.ncdc.noaa.gov/cag/) (National Oceanic and Atmospheric Administration - Administración Nacional Oceánica y Atmosférica). Siéntete libre de jugar con la página web y analizar datos por tu cuenta, pero por ahora, buscaremos asegurarnos que trabajaremos con el mismo conjunto de datos.\n", + "\n", + "Tenemos un archivo llamado `land_global_temperature_anomaly-1880-2016.csv` en nuestra carpeta `data`. Este archivo contiene el año en la primera columna y los promedios de la anomalía de la temperatura terrestre enumerados secuencialmente en la segunda columna, desde el año 1880 hasta 2016. Cargaremos el archivo y luego haremos una gráfica inicial para ver cómo se ven estos datos.\n", + "\n", + "##### Nota:\n", + "\n", + "Si descargó este notebook por separado en lugar de la colección completa de este curso, es posible que no tenga el archivo de datos en la ubicación que suponemos a continuación. En ese caso, puede descargar los datos si agrega una celda de código y ejecuta el siguiente código en ella:\n", + "\n", + "```Python\n", + "from urllib.request import urlretrieve\n", + "URL = 'http://go.gwu.edu/engcomp1data5?accessType=DOWNLOAD'\n", + "urlretrieve (URL, 'land_global_temperature_anomaly-1880-2016.csv')\n", + "```\n", + "\n", + "El archivo de datos se descargará a su directorio de trabajo, y luego tendrá que eliminar la información de ruta, es decir, la cadena `'../data /'`, de la definición de la variable `fname` a continuación.\n", + "\n", + "Comencemos importando NumPy." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Para cargar nuestros datos desde el archivo, utilizaremos la función [`numpy.loadtxt()`](https://docs.scipy.org/doc/numpy/reference/generated/numpy.loadtxt.html), que nos permite guardar inmediatamente los datos en arrays de NumPy. (Le recomendamos que lea la documentación para obtener detalles sobre cómo funciona la función). Guardaremos los datos en los arrays `year` y `temp_anomaly`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fname = '../data/land_global_temperature_anomaly-1880-2016.csv'\n", + "\n", + "year, temp_anomaly = numpy.loadtxt(fname, delimiter=',', skiprows=5, unpack=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##### Ejercicio\n", + "\n", + "Inspeccione los datos imprimiendo `year` y` temp_anomaly`." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Paso 2: graficando los datos\n", + "\n", + "Primero cargaremos el módulo `pyplot` de **Matplotlib**, para hacer gráficos en 2D. Recuerda que para obtener los gráficos dentro del notebook de jupyter, usamos un comando especial \"mágico\", `%matplotlib inline`:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from matplotlib import pyplot\n", + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "La función `plot()` del módulo `pyplot` hace gráficos de líneas simples. Evitaremos los textos que aparecen en la parte superior de la figura, que dicen `Out [x]:[<...>]`, al agregar un punto y coma al final del comando de trazado." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pyplot.plot(year, temp_anomaly);" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "collapsed": true + }, + "source": [ + "Ahora tenemos un diagrama de líneas, pero si miras esta gráfica sin ninguna información, ¡no podrás averiguar qué tipo de datos son! Necesitamos etiquetas en los ejes, un título y un mejor color, fuente y tamaño para los ejes.\n", + "\n", + "Siempre debes apuntar a generar **gráficos de calidad de publicación**.\n", + "\n", + "La forma en que presentes tus datos permitirá a otros (y probablemente a tí mismo en el futuro) comprender mejor tu trabajo.\n", + "\n", + "Podemos personalizar el estilo de nuestras tramas usando los parámetros de configuración de **Matplotlib**: [`rcParams`](https://matplotlib.org/api/matplotlib_configuration_api.html#matplotlib.rcParams). Esto nos permite establecer algunas opciones de estilo que se aplican a todos los gráficos que se crearán a continuación. \n", + "\n", + "Por ejemplo, crearemos la fuente de un tamaño y tipo específico. También puedes personalizar otros parámetros como el ancho de línea, el color, etc. Consulta la documentación para más detalle." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from matplotlib import rcParams\n", + "rcParams['font.family'] = 'serif'\n", + "rcParams['font.size'] = 16" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Volveremos a hacer el mismo grafico, pero ahora agregaremos algunas cosas para que sea más bello y de **calidad de publicación**. Agregaremos un título, etiquetaremos los ejes, y mostraremos una cuadrícula de fondo. ¡Estudia los comandos a continuación y observa el resultado!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#Puedes modificar el tamaño de la figura\n", + "pyplot.figure(figsize=(10,5))\n", + "\n", + "#Graficando\n", + "pyplot.plot(year, temp_anomaly, color='#2929a3', linestyle='-', linewidth=1) \n", + "pyplot.title('Anomalías de temperatura global.\\n') # Land global temperature anomalies\n", + "pyplot.xlabel('Año') # Year\n", + "pyplot.ylabel('Anomalía de temperatura [°C]') # Land temperature anomaly\n", + "pyplot.grid();" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "collapsed": true + }, + "source": [ + "¿Mucho mejor, no? Siéntete libre de jugar con los parámetros y ver cómo cambia el gráfico. No hay nada mejor que probar y equivocarse para entender el funcionamiento." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Paso 3: Realizando una regresión lineal de mínimos cuadrados\n", + "\n", + "Para tener una idea del comportamiento general de nuestros datos, podemos buscar una curva suave que (de manera aproximada) se ajuste a los puntos. Generalmente buscamos una curva que sea simple (por ejemplo, un polinomio) y no reproduzca el ruido que siempre está presente en los datos experimentales.\n", + "\n", + "Sea $f(x)$ sea la función que ajustaremos a los $n+1$ puntos de datos: $(x_i, y_i)$, $i = 0, 1, ..., n$:\n", + "\n", + "$$\n", + "    f (x) = f (x; a_0, a_1, ..., a_m)\n", + "$$\n", + "\n", + "La notación anterior significa que $f$ es una función de $x$, con $m + 1$ parámetros variables $a_0, a_1, ..., a_m$, donde $m\n", + "```\n", + "\n", + "El **docstring** (documentación) de una función es un mensaje del programador que documenta lo que se construyó. Un docstrings debe ser descriptivo y conciso. Son importantes porque explican (o recuerdan) el uso previsto de la función para los usuarios. Más adelante puede acceder a la cadena de documentación de una función usando la función `help()` y pasando el nombre de la función. Si está en un notebook, también puedes anteponer un signo de interrogación `?` antes del nombre de la función y ejecutar en una celda para mostrar la información de una función.\n", + "\n", + "¡Intentalo!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "?print" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Usando la función `help` en su lugar:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "help(print)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Definamos una función personalizada que calcula el valor promedio de cualquier array. Estudia el código a continuación con cuidado." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def mean_value(array):\n", + " \"\"\" Calcular el valor promedio de un array\n", + " \n", + " Argumentos\n", + " ---------\n", + " array: array de Numpy\n", + " \n", + " Regresa\n", + " ------- \n", + " mean: valor promedio de una array\n", + " \"\"\"\n", + " sum_elem = 0\n", + " for element in array:\n", + " sum_elem += element # Esto es equivalente a sum_elem = sum_elem + element\n", + " \n", + " mean = sum_elem / len(array)\n", + " \n", + " return mean\n", + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Una vez que se ejecuta la celda de arriba, la función `mean_value()` está disponible para usar en cualquier argumento del tipo correcto. Esta función funciona en arrays de cualquier longitud. Podemos intentarlo ahora con nuestros datos." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "year_mean = mean_value(year)\n", + "print(year_mean)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "temp_anomaly_mean = mean_value(temp_anomaly)\n", + "print(temp_anomaly_mean)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "¡Genial! Aprendiste cómo escribir una función de Python, y creamos una función para calcular el valor promedio de un array de números. No teníamos que hacerlo, porque NumPy tiene una función incorporada para hacer exactamente lo que necesitamos: [`numpy.mean()`](https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.mean.html). En general, resulta una práctica conveniente verificar que las funciones que necesitas no existan en las librerías que estás utilizando." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##### Ejercicio\n", + "\n", + "Calcula el promedio de los arrays `year` y` temp_anomaly` utilizando la función incorporada de NumPy, y compara los resultados con los obtenidos utilizando nuestra función personalizada `mean_value`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Ahora que tenemos valores medios, podemos calcular nuestros coeficientes siguiendo las ecuaciones. Primero calculamos $ a_1 $ y luego usamos ese valor para calcular $ a_0 $.\n", + "\n", + "Nuestros coeficientes son:\n", + "\n", + "$$\n", + "    a_1 = \\frac {\\sum_ {i = 0} ^ {n} y_ {i} (x_i - \\bar{x})} {\\sum_ {i = 0} ^ {n} x_i (x_i - \\bar{x})} \\quad, \\quad a_0 = \\bar{y} - a_1 \\bar{x}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Ya calculamos los valores promedios de los arrays de datos, pero la fórmula requiere dos sumas sobre nuevos arrays. Pero adivina, NumPy tiene una función incorporada para eso: [`numpy.sum()`](https://docs.scipy.org/doc/numpy/reference/generated/numpy.sum.html). Estudia el código a continuación." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "a_1 = numpy.sum(temp_anomaly*(year - year_mean)) / numpy.sum(year*(year - year_mean)) " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(a_1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "a_0 = temp_anomaly_mean - a_1*year_mean" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(a_0)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##### Ejercicio\n", + "\n", + "Escribe una función que calcule los coeficientes, llama a esta función para calcularlos y compara el resultado con los valores que obtuvimos antes. Como una pista, te damos la estructura que debes seguir:\n", + "\n", + "```python\n", + "def coeficients(x, y, x_mean, y_mean):\n", + "    \"\"\"\n", + "    Escribir docstrings aquí\n", + "    \"\"\"\n", + "    a_1 =\n", + "    a_0 =\n", + "    \n", + "    returns a_1, a_0\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Ahora tenemos los coeficientes de la función lineal que mejor se ajusta a nuestros datos. Con ellos, podemos calcular los valores predichos de anomalía de temperatura, de acuerdo con nuestro ajuste. Verifica nuevamente las ecuaciones anteriores: los valores que vamos a calcular son $f(x_i)$.\n", + "\n", + "Llamemos a `reg` al array obtenido al evaluar $f(x_i)$ para todos los años." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "reg = a_0 + a_1 * year" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Con los valores de nuestra regresión lineal, podemos trazarla sobre los datos originales para ver cómo se ven juntos. Estudia el código a continuación." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pyplot.figure(figsize=(10, 5))\n", + "\n", + "pyplot.plot(year, temp_anomaly, color='#2929a3', linestyle='-', linewidth=1, alpha=0.5) \n", + "pyplot.plot(year, reg, 'k--', linewidth=2, label='Regresión lineal')\n", + "pyplot.xlabel('Año')\n", + "pyplot.ylabel('Anomalía de temperatura[°C]')\n", + "pyplot.legend(loc='best', fontsize=15)\n", + "pyplot.grid();" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Paso 4: aplicando la regresión usando NumPy" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Anteriormente codificamos la regresión lineal desde cero. Pero, como ya habrás supuesto, no era necesario hacerlo porque NumPy tiene funciones integradas que cubren muchas de nuestras necesidades.\n", + "\n", + "¡Sí! ¡Python y NumPy están aquí para ayudar! Con [`polyfit()`](https://docs.scipy.org/doc/numpy-1.10.0/reference/generated/numpy.polyfit.html), obtenemos la pendiente y el intercepto en $y$ de la línea que mejor se ajusta a los datos. Con [`poly1d()`](https://docs.scipy.org/doc/numpy/reference/generated/numpy.poly1d.html), podemos construir la función lineal desde su pendiente y su intercepto en $y$.\n", + "\n", + "Observémoslo en acción:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Primero ajustar con NumPy, y obtener los parámetros a_1n, a_0n:\n", + "a_1n, a_0n = numpy.polyfit(year, temp_anomaly, 1)\n", + "\n", + "f_linear = numpy.poly1d((a_1n, a_0n)) " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(a_1n)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(a_0n)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(f_linear)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pyplot.figure(figsize=(10, 5))\n", + "\n", + "pyplot.plot(year, temp_anomaly, color='#2929a3', linestyle='-', linewidth=1, alpha=0.5) \n", + "pyplot.plot(year, f_linear(year), 'k--', linewidth=2, label='Regresión lineal')\n", + "pyplot.xlabel('Año')\n", + "pyplot.ylabel('Anomalía de temperatura en tierra [°C]')\n", + "pyplot.legend(loc='best', fontsize=15)\n", + "pyplot.grid();" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## \"Regresión dividida\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Si nos fijamos en el gráfico anterior, observarás que alrededor de 1970 la temperatura comienza a aumentar más rápido que la tendencia anterior. Una sola línea recta no nos dará un ajuste lo suficientemente bueno.\n", + "\n", + "¿Qué pasa si dividimos los datos en dos (antes y después de 1970) y realizamos una regresión lineal en cada segmento?\n", + "\n", + "Para hacer eso, necesitamos encontrar el lugar en nuestro aray `year` donde se encuentra el año 1970. Afortunadamente, NumPy tiene una función llamada [`numpy.where()`](https://docs.scipy.org/doc/numpy/reference/generated/numpy.where.html) que nos puede ayudar. Pasamos una condición y `numpy.where()` nos dice en qué parte del array la condición es `True`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "numpy.where(year==1970)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Para dividir los datos, usamos el poderoso instrumento de _slicing_ con la notación de dos puntos. Recuerde que un punto entre dos índices indica un rango de valores desde `start`(inicio) hasta `end` (fin). La regla es que `[start: end]` incluye el elemento en el índice `start` pero excluye el correspondiente al índice` end`. Por ejemplo, para obtener los primeros 3 años en nuestro array `year`, hacemos:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "year[0:3]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Ahora sabemos cómo dividir nuestros datos en dos conjuntos, para obtener dos líneas de regresión. Necesitamos dos sectores de los arrays `year` y` temp_anomaly`, que guardaremos en los nuevos nombres de variables a continuación. Después de eso, completamos dos ajustes lineales utilizando las útiles funciones de NumPy que aprendimos anteriormente." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "year_1 , temp_anomaly_1 = year[0:90], temp_anomaly[0:90]\n", + "year_2 , temp_anomaly_2 = year[90:], temp_anomaly[90:]\n", + "\n", + "m1, b1 = numpy.polyfit(year_1, temp_anomaly_1, 1)\n", + "m2, b2 = numpy.polyfit(year_2, temp_anomaly_2, 1)\n", + "\n", + "f_linear_1 = numpy.poly1d((m1, b1))\n", + "f_linear_2 = numpy.poly1d((m2, b2))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pyplot.figure(figsize=(10, 5))\n", + "\n", + "pyplot.plot(year, temp_anomaly, color='#2929a3', linestyle='-', linewidth=1, alpha=0.5) \n", + "pyplot.plot(year_1, f_linear_1(year_1), 'g--', linewidth=2, label='1880-1969')\n", + "pyplot.plot(year_2, f_linear_2(year_2), 'r--', linewidth=2, label='1970-2016')\n", + "\n", + "pyplot.xlabel('Año')\n", + "pyplot.ylabel('Anomalía de Temperatura en Tierra [°C]')\n", + "pyplot.legend(loc='best', fontsize=15)\n", + "pyplot.grid();" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Tenemos dos curvas diferentes para dos secciones diferentes de nuestro conjunto de datos. Un pequeño problema con esto es que el punto final de nuestra primera regresión no coincide con el punto de partida de la segunda regresión. Hicimos esto con el propósito de aprender, pero no es rigurosamente correcto. Lo arreglaremos en el próximo módulo del curso cuando aprendamos más sobre los diferentes tipos de regresión." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Aprendimos:\n", + "\n", + "* Hacer gráficos más bellos\n", + "* Definir y llamar funciones de Python personalizadas\n", + "* Aplicar regresión lineal a datos\n", + "* Funciones nativas de NumPy para regresión lineal\n", + "* ¡La Tierra se está calentando!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Referencias\n", + "1. [_Essential skills for reproducible research computing_](https://barbagroup.github.io/essential_skills_RRC/) (Habilidades esenciales para la informática de investigación reproducible, 2017). Lorena A. Barba, Natalia C. Clementi, Gilbert Forsyth. \n", + "2. _Numerical Methods in Engineering with Python 3_ (Métodos numéricos en ingeniería con Python 3, 2013). Jaan Kiusalaas. Cambridge University Press.\n", + "3. _Effective Computation in Physics: Field Guide to Research with Python_ (Cálculo eficaz en física: Guía de campo para la investigación con Python, 2015). Anthony Scopatz & Kathryn D. Huff. O'Reilly Media, Inc." + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Ejecuta esta celda para cargar el notebook con estilo, \n", + "# pero puedes ignorar su contenido.\n", + "from IPython.core.display import HTML\n", + "css_file = '../style/custom.css'\n", + "HTML(open(css_file, \"r\").read())" + ] + } + ], + "metadata": { + "anaconda-cloud": {}, + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.5.2" + }, + "widgets": { + "state": {}, + "version": "1.1.2" + } + }, + "nbformat": 4, + "nbformat_minor": 1 +}