Este repositorio es una compilación de los ejercicios que realicé para el curso de "Programación en Python" en el marco del proyecto de Inteligencia Artificial Interdisciplinaria, la Escuela de Ciencia y Tecnología de la UNSAM. Es un curso de programación en Python para poder programar algoritmos y comprender los métodos desarrollados por otros. Está orientado a profundizar en temas de análisis y visualización de datos, aprendizaje automático, modelado matemático y desarrollo de scripts. Cabe destacar que semana a semana participamos en la corrección entre pares que nos permite aprender tanto a leer código de otro programador como a visualizar un problema desde otro punto de vista.
Para poder testear los ejercicios se puede clonar este repositorio e instalar los módulos que sean necesarios (los que se mencionan como importados) y correr los scripts en un IDE.
En esta clase aprendimos a correr el intérprete de Python desde la línea de comandos para usarlo como una calculadora. Aprendimos a editar programas con un editor de texto y a correrlos en la terminal. Vimos diferentes tipos de datos: números enteros, números de punto flotante, cadenas y listas.
Para escribir programas útiles, necesitamos aprender a trabajar con datos. En esta clase introducimos las estructuras de datos elementales de Python que nos faltan: tuplas, conjuntos y diccionarios y profundizamos un poco más en las listas y sus usos. También comenzamos a ver cómo estructurar el código usando funciones y a leer archivos.
En esta clase discutimos los tipos de errores que pueden aparecer en un programa (bugs) e introducimos algunas técnicas primitivas para buscarlos. Para escribir programas útiles, necesitamos aprender a trabajar con datos. En esta clase vas a escribir un programa que lee un archivo de datos en formato csv y realiza un cálculo simple. Vas a aprender a estructurar tu código creando funciones y estructuras de datos un poco más complejas como tuplas, conjuntos y diccionarios. Esta clase comenzamos a utilizar un entorno de desarrollo integrado (IDE). Vamos a trabajar con datos reales sobre los árboles de la ciudad de Buenos Aires en espacios públicos.
En esta clase introducimos el debugger y les proponemos una serie de ejercicios donde tienen que escribir algoritmos que operen sobre listas. Luego introducimos la comprensión de listas, un concepto muy hermoso y pythonesco. Cerramos la clase con una discusión sobre el concepto de objeto que subyace al lenguaje y algunos ejercicios para repasar estos conceptos usando el dataset de la clase anterior.
En esta clase introducimos conceptos y técnicas relacionadas con el azar. La aleatoriedad puede ser una gran aliada a la hora de realizar cálculos de fenómenos estocásticos pero también de fenómenos deterministas. Introducimos los números pseudoaleatorios, así como el módulo numpy y sus métodos más sencillos. Presentamos una versión libre de un ejercicio que te guía para que resuelvas la pregunta ¿cuántos paquetes de figuritas tengo que comprar para llenar un álbum? con un enfoque estadístico usando el método de Montecarlo. Introducimos los arrays de la biblioteca numpy en una sección un poco técnica pero importante para el futuro. A lo largo de la clase iremos haciendo nuestros primeros gráficos en Python. Cerramos introduciendo los scatterplots que permiten visualizar dos variables en simultáneo y facilitan el análisis exploratorio de datos.
Hasta aquí aprendimos algunas cosas básicas de Python y escribimos nuestros primeros programa. A medida que escribas programas más grandes, vas a necesitar organizarlos un poco mejor. En esta clase trataremos con mayor detalle cómo escribir funciones y módulos propios. En la segunda mitad retomamos nuestra discusión sobre algoritmos de búsqueda e introducimos la búsqueda binaria, un algoritmo mucho más eficiente para buscar un elemento en un vector. Discutimos algunos conceptos de la teoría de la complejidad y finalmente haremos unos gráficos para comparar visualmente la cantidad de operaciones que realizan dos métodos de búsqueda.
En este curso queremos que aprendas a escribir un script que te resuelva un problema computacional. Pero también queremos que puedas escribir adecuadamente programas más grandes, que los puedas compartir y volver a usar. Por eso insistimos con algunos temas de estilo, documentación, especificiación y diseño que ya hemos comentado anteriormente y sobre los que volveremos en esta clase. Uno de ellos es que es conveniente administrar los errores; seguiremos hablando sobre las formas adecuadas de hacerlo y porqué no conviene hacerlo de más. También se vuelve indispensable estructurar adecuadamente el código y aprender a definir una función main. Vamos a continuar con nuestras discusiones sobre el diseño de algoritmos y sus estructuras de datos asociadas. También queremos que aprendas algunos conceptos elementales sobre especificación de problemas. Son procesos de abstracción que nos ayudan a pensar con mayor claridad. Al especificar un problema con precondiciones y poscondiciones estamos definiendo qué es lo que debe pasar en una función, por ejemplo (aunque en ningún momento decimos cómo debe pasar esto). Una especificación es como un contrato y podemos definir varias funciones que cumplan el contrato, y cada una puede resolverlo a su manera. Finalmente, daremos un poco más sistemáticamente algunos conceptos de la biblioteca matplotlib, incluyendo el manejo de figuras y subplots.
En esta clase introducimos el módulo datetime para manejar datos relacionados con el tiempo y un par de funciones del módulo os para leer directorios, procesar archivos y realizar algunas tareas relacionadas con el sistema operativo. Luego te proponemos integrar esto para hacer un script que corra desde línea de comandos y te permita ordenar los archivos de cierto tipo. En la segunda mitad introducimos el módulo Pandas y el tipo DataFrame así como algunos de sus métodos elementales. Usamos pandas para analizar dos datasets de Arbolado Porteño graficando algunos de sus datos. En esta parte tenés que comparar caracterísiticas de árboles que crecen en los parques con otros que crecen en las veredas. En la última parte te proponemos análizar ondas de mareas en el Río de la Plata como excusa para introducir el procesamiento de series temporales. Nos metemos un poco en temas específicos con una última parte optativa que incluye un breve análsis de la transformada de Fourier para medir el tiempo que tarda esta onda de marea en trasladarse de un puerto a otro.
En esta clase vamos a meternos con la programación orientada a objetos. Vamos a ver los conceptos de clases y objetos. Hasta ahora los programas que escribimos usaron sólo tipos de datos nativos de Python, con la instrucción class vamos a definir nuevas clases. Vamos a ir más allá y a hablar del concepto de herencia, una herramienta comúnmente usada para escribir programas extensibles. Por último, vamos a referirnos a algunos métodos especiales de los objetos de Python. En los ejercicios vamos a ver los conceptos de pilas y colas. En particular, la pila de llamadas nos prepara el camino para poder estudiar el concepto de recursión.
Programar es básicamente escribir condicionales, ciclos y asignaciones de variables. Aunque no de cualquier forma. Los ciclos, ya sean ciclos while o iteraciones for son una de las estructuras más ubicuas en cualquier lenguaje. Los programas hacen muchas iteraciones para procesar listas, leer archivos, buscar en bases de datos y demás. Una de las características más poderosas de Python es la capacidad de redefinir la iteración mediante las llamadas "funciones generadoras". En esta sección veremos de qué se trata esto. Hacia el final vas a escribir programas que procesan datos en tiempo real, a medida que son generados.
En esta clase discutimos el concepto de recursión, proponemos algunas bases para el diseño de algoritmos recursivos y elaboramos algunos ejemplos con ellos, algunos un tanto esotéricos. En otro orden de cosas, en la última sección damos un acercamiento práctico a las técnicas de regresión lineal.
Ordenar una lista de números es una de las tareas fundamentales que realiza un ordenador (también llamado computadora). Los algoritmos conceptualmente más sencillos tienen una complejidad computacional (en el peor caso) que crece de forma cuadrática (n^2) con la longitud, n, de la lista a ordenar. Veremos en detalle dos algoritmos sencillos: el algoritmo de selección y el de inserción y luego divide and conquer que lleva a la idea de merge sort.
Si necesitas soporte, podes comunicarte conmigo.
Este repositorio está abierto a contribuciones, no dudes en hacerlo!
Todo el código que ha sido escrito forma parte de la resolución de los problemas planteados por los docentes del curso y es de mi autoría.