├── .github └── workflows │ └── jekyll.yml ├── .gitignore ├── A - Intro a Python.ipynb ├── B - Intro a NumPy.ipynb ├── C - Intro a Pandas.ipynb └── README.md /.github/workflows/jekyll.yml: -------------------------------------------------------------------------------- 1 | # This workflow uses actions that are not certified by GitHub. 2 | # They are provided by a third-party and are governed by 3 | # separate terms of service, privacy policy, and support 4 | # documentation. 5 | 6 | # Sample workflow for building and deploying a Jekyll site to GitHub Pages 7 | name: Deploy Jekyll site to Pages 8 | 9 | on: 10 | # Runs on pushes targeting the default branch 11 | push: 12 | branches: ["gh-pages"] 13 | 14 | # Allows you to run this workflow manually from the Actions tab 15 | workflow_dispatch: 16 | 17 | # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages 18 | permissions: 19 | contents: read 20 | pages: write 21 | id-token: write 22 | 23 | # Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. 24 | # However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. 25 | concurrency: 26 | group: "pages" 27 | cancel-in-progress: false 28 | 29 | jobs: 30 | # Build job 31 | build: 32 | runs-on: ubuntu-latest 33 | steps: 34 | - name: Checkout 35 | uses: actions/checkout@v4 36 | - name: Setup Ruby 37 | # https://github.com/ruby/setup-ruby/releases/tag/v1.207.0 38 | uses: ruby/setup-ruby@4a9ddd6f338a97768b8006bf671dfbad383215f4 39 | with: 40 | ruby-version: '3.1' # Not needed with a .ruby-version file 41 | bundler-cache: true # runs 'bundle install' and caches installed gems automatically 42 | cache-version: 0 # Increment this number if you need to re-download cached gems 43 | - name: Setup Pages 44 | id: pages 45 | uses: actions/configure-pages@v5 46 | - name: Build with Jekyll 47 | # Outputs to the './_site' directory by default 48 | run: bundle exec jekyll build --baseurl "${{ steps.pages.outputs.base_path }}" 49 | env: 50 | JEKYLL_ENV: production 51 | - name: Upload artifact 52 | # Automatically uploads an artifact from the './_site' directory by default 53 | uses: actions/upload-pages-artifact@v3 54 | 55 | # Deployment job 56 | deploy: 57 | environment: 58 | name: github-pages 59 | url: ${{ steps.deployment.outputs.page_url }} 60 | runs-on: ubuntu-latest 61 | needs: build 62 | steps: 63 | - name: Deploy to GitHub Pages 64 | id: deployment 65 | uses: actions/deploy-pages@v4 66 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .sass-cache/ 3 | Gemfile.lock 4 | _photos/ 5 | _site/ 6 | assets/ -------------------------------------------------------------------------------- /A - Intro a Python.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "A - Intro a Python", 7 | "provenance": [], 8 | "collapsed_sections": [], 9 | "include_colab_link": true 10 | }, 11 | "kernelspec": { 12 | "name": "python3", 13 | "display_name": "Python 3" 14 | } 15 | }, 16 | "cells": [ 17 | { 18 | "cell_type": "markdown", 19 | "metadata": { 20 | "id": "view-in-github", 21 | "colab_type": "text" 22 | }, 23 | "source": [ 24 | "\"Open" 25 | ] 26 | }, 27 | { 28 | "cell_type": "markdown", 29 | "metadata": { 30 | "id": "OpSHrtcJLQEU" 31 | }, 32 | "source": [ 33 | "# Introducción a Python\n", 34 | "\n", 35 | "A lo largo de este cuaderno explicaremos algunos conceptos básicos de Python. Los temas específicos que cubriremos en estos cuadernos introductorios son los siguientes:\n", 36 | "\n", 37 | "1. ¿Qué es Python?\n", 38 | "2. _Variables_: tipos, declaraciones y operaciones\n", 39 | "3. _Control de flujo_ - Condicionales y bucles\n", 40 | "4. Objetos avanzados: _Listas_ y _diccionarios_\n", 41 | "5. Empaquetando código - _Funciones_\n", 42 | "\n", 43 | "### Planteamiento del problema:\n", 44 | "\n", 45 | "Imagina que queremos crear un directorio que contenga toda la información de los estudiantes de nuestro club. Para ello, necesitaremos construir paso a paso la idea completa del proyecto.\n", 46 | "\n", 47 | "Para ello, necesitamos saber sobre tipos de variables, objetos avanzados como listas y diccionarios, cómo crear funciones para operar algunos valores y cómo crear nuevos objetos.\n", 48 | "\n", 49 | "> #### ¿Qué tenemos que hacer?\n", 50 | ">\n", 51 | "> En concreto, vamos a hacer lo siguiente:\n", 52 | "> - Crearemos una lista de diccionarios que contienen la información de los estudiantes\n", 53 | "> - Cada diccionario contendrá los siguientes atributos:\n", 54 | "> - Nombre ``\n", 55 | "> - Edad ``\n", 56 | "> - Temas ``\n", 57 | "> - Menores de edad ``\n", 58 | "> - Crea una función que solicita automáticamente información del estudiante\n", 59 | "\n", 60 | "\n", 61 | "## ¿Qué es Python?\n", 62 | "\n", 63 | "
\n", 64 | " \n", 65 | "
\n", 66 | "\n", 67 | "Python es un lenguaje de programación **interpretado**, lo que significa que un _interpretador_ ejecuta y ejecuta su código línea por línea en lugar de compilarlo. Python tiene una sintaxis elegante que te obliga a **aplicar sangría a tu código para construir bloques de código**, por lo que Python no usa `{}` para bloques de código. No es común usar punto y coma en Python (`;`) al final de cualquier oración. Otra cosa interesante de Python es que no necesita declarar variables, solo las define, y sucede que Python **se escribe dinámicamente**.\n", 68 | "\n", 69 | "### Hola mundo en Python\n", 70 | "\n", 71 | "Usaremos las funciones de entrada y salida de Python para crear nuestro primer hola mundo.\n", 72 | "\n", 73 | "Solo necesita ejecutar la siguiente celda con código presionando el botón _play_ o presionando `Shift + Enter` en su teclado." 74 | ] 75 | }, 76 | { 77 | "cell_type": "code", 78 | "metadata": { 79 | "id": "lBy00gJgHaQo" 80 | }, 81 | "source": [ 82 | "# Hello world in Python:\n", 83 | "your_name = input(\"Please write your name: \")\n", 84 | "print(f\"Say hello to the world, {your_name}!\")" 85 | ], 86 | "execution_count": null, 87 | "outputs": [] 88 | }, 89 | { 90 | "cell_type": "markdown", 91 | "metadata": { 92 | "id": "RSJW87sPXOAh" 93 | }, 94 | "source": [ 95 | "## Variables\n", 96 | "\n", 97 | "Python tiene varios tipos de variables de forma nativa. Comenzando con variables numéricas, Python puede trabajar con números enteros, números flotantes y números complejos. También cuenta con cadenas de caracteres para trabajar con texto y otro tipo de variables llamadas booleanos para guardar valores binarios.\n", 98 | "\n", 99 | "La forma en que declaramos las variables es la siguiente:\n", 100 | "\n", 101 | "```python\n", 102 | "variable_name = \n", 103 | "```\n", 104 | "\n", 105 | "El nombre de una variable no puede tener espacios, debe comenzar con una letra, puede contener letras mayúsculas o números dentro del nombre.\n", 106 | "\n", 107 | "#### Ejemplo:\n", 108 | "\n", 109 | "```python\n", 110 | "my_dog = \"Mirlo\"\n", 111 | "```\n", 112 | "\n", 113 | "Para obtener el tipo de una variable, podemos usar la función `type ()` y pasar como parámetro la variable que queremos conocer.\n", 114 | "\n", 115 | "#### Ejemplo:\n", 116 | "\n", 117 | "```python\n", 118 | "type(my_dog)\n", 119 | "```\n", 120 | "\n", 121 | "\n", 122 | "¿Qué sucede si ejecuto el bloque previo de código?" 123 | ] 124 | }, 125 | { 126 | "cell_type": "code", 127 | "metadata": { 128 | "id": "8i5sDqw-XUJP" 129 | }, 130 | "source": [ 131 | "# TODO.\n", 132 | "# Declare a variable named my_dog and set it with a dog's name.\n", 133 | "# Print the type of that variable.\n" 134 | ], 135 | "execution_count": null, 136 | "outputs": [] 137 | }, 138 | { 139 | "cell_type": "markdown", 140 | "metadata": { 141 | "id": "nlMAcIGEYIef" 142 | }, 143 | "source": [ 144 | "Hay varios tipos de variables, ¡incluso números complejos en Python!\n", 145 | "\n", 146 | "#### Ejercicio:\n", 147 | "\n", 148 | "Define e imprime el tipo y valor de las variables denominadas:\n", 149 | "- `name`, debe ser un` `que contenga cualquier nombre\n", 150 | "- `age`, debe ser un` `que contenga cualquier edad\n", 151 | "- `pi`, debe ser un` `que contenga su mejor aproximación a pi\n", 152 | "- `modulus_one`, debe ser un ``que tiene [módulo](https://en.wikipedia.org/wiki/Absolute_value#Complex_numbers) uno" 153 | ] 154 | }, 155 | { 156 | "cell_type": "code", 157 | "metadata": { 158 | "id": "RmbbjQIqYT6i" 159 | }, 160 | "source": [ 161 | "# TODO.\n", 162 | "# Define sample variables and print each type and value.\n" 163 | ], 164 | "execution_count": null, 165 | "outputs": [] 166 | }, 167 | { 168 | "cell_type": "markdown", 169 | "metadata": { 170 | "id": "U_cKNLU3YnP8" 171 | }, 172 | "source": [ 173 | "## Control de flujo (condicionales)\n", 174 | "\n", 175 | "Hasta ahora, sabemos cómo definir variables, por lo que podemos crear bloques de código un poco más avanzados. Lo primero que queremos hacer es crear una nueva variable llamada `under_age` y necesitaremos definirla usando una declaración contitional. Para ello, será útil recordar los operadores de comparación (`<, >, <=, >=, ==, !=`).\n", 176 | "\n", 177 | "La idea es la siguiente, si la persona es menor de edad, el valor de esta variable será \"Verdadero\" y será \"Falso\" en el otro caso.\n", 178 | "\n", 179 | "Para declarar una declaración condicional, se usa la siguiente sintaxis:\n", 180 | "\n", 181 | "```python\n", 182 | "if condition:\n", 183 | " # Block of code for a satisfied condition \n", 184 | "else:\n", 185 | " # Block of code for a non-satisfied condition \n", 186 | "```\n", 187 | "\n", 188 | "#### Ejemplo:\n" 189 | ] 190 | }, 191 | { 192 | "cell_type": "code", 193 | "metadata": { 194 | "id": "9oJook66anxJ" 195 | }, 196 | "source": [ 197 | "dog_color = \"black\"\n", 198 | "if color == \"black\":\n", 199 | " print(\"Indeed, this dog is black.\")\n", 200 | "else:\n", 201 | " print(\"Nope, it is not a black dog.\")" 202 | ], 203 | "execution_count": null, 204 | "outputs": [] 205 | }, 206 | { 207 | "cell_type": "markdown", 208 | "metadata": { 209 | "id": "XYjNLN8VjFfK" 210 | }, 211 | "source": [ 212 | "En el caso de tener más de una condición, podemos usar declaraciones `elif`:\n", 213 | "\n", 214 | "```python\n", 215 | "if condition_one:\n", 216 | " # Block of code for a satisfied condition one\n", 217 | "elif condition_two:\n", 218 | " # Block of code for a satisfied condition two\n", 219 | "...\n", 220 | "elif condition_nth:\n", 221 | " # Block of code for a satisfied condition nth\n", 222 | "else:\n", 223 | " # Block of code for non-satisfied conditions\n", 224 | "```\n", 225 | "\n", 226 | "#### Ejercicio:\n", 227 | "\n", 228 | "Ahora crea una condición para definir una nueva variable llamada `under_age` que comparará si la edad es mayor o igual a 18 para establecerla como \"Falso\" o \"Verdadero\" en el otro caso." 229 | ] 230 | }, 231 | { 232 | "cell_type": "code", 233 | "metadata": { 234 | "id": "xcu423b2liUI" 235 | }, 236 | "source": [ 237 | "# TODO.\n", 238 | "# Write a conditional to set the age.\n" 239 | ], 240 | "execution_count": null, 241 | "outputs": [] 242 | }, 243 | { 244 | "cell_type": "markdown", 245 | "metadata": { 246 | "id": "rhmQtvUmnNNx" 247 | }, 248 | "source": [ 249 | "## Listas\n", 250 | "\n", 251 | "Una lista es una colección ordenada de cualquier tipo de variables. La sintaxis utilizada para la lista es la siguiente:\n", 252 | "\n", 253 | "```python\n", 254 | "list_name = [first_element, second_element, etcetera]\n", 255 | "```\n", 256 | "\n", 257 | "Las reglas de nomenclatura son las mismas que para otras variables.\n", 258 | "\n", 259 | "Puedes declarar una lista vacía simplemente estableciendo corchetes `[]`. Si desea agregar un elemento al final de una lista, usamos el método `.append (x)`, donde `x` sería el elemento que queremos insertar.\n", 260 | "\n", 261 | "#### Ejemplo:" 262 | ] 263 | }, 264 | { 265 | "cell_type": "code", 266 | "metadata": { 267 | "id": "5f8xkD-VoerM" 268 | }, 269 | "source": [ 270 | "# Example list:\n", 271 | "prime_numbers = [2, 3, 5, 7, 11]\n", 272 | "print(prime_numbers)\n", 273 | "prime_numbers.append(13)\n", 274 | "print(prime_numbers)" 275 | ], 276 | "execution_count": null, 277 | "outputs": [] 278 | }, 279 | { 280 | "cell_type": "markdown", 281 | "metadata": { 282 | "id": "yP1GTen8ovX9" 283 | }, 284 | "source": [ 285 | "Para acceder a los valores de una lista, utilizamos la indexación, lo que significa que cada elemento tiene un índice asociado. Para acceder al elemento asociado usaremos el índice entre corchetes.\n", 286 | "\n", 287 | "####Ejemplo:\n", 288 | "\n", 289 | "En nuestros `prime_numbers` obtendríamos los elementos correspondientes de la siguiente manera:" 290 | ] 291 | }, 292 | { 293 | "cell_type": "code", 294 | "metadata": { 295 | "id": "xAevC47uqN7i" 296 | }, 297 | "source": [ 298 | "# We can access the elements:\n", 299 | "print(\"First element: \", prime_numbers[0])\n", 300 | "print(\"Second element: \", prime_numbers[1])\n", 301 | "print(\"Third element: \", prime_numbers[2])\n", 302 | "\n", 303 | "# We can even access using negative indices:\n", 304 | "print(\"Last element: \", prime_numbers[-1])" 305 | ], 306 | "execution_count": null, 307 | "outputs": [] 308 | }, 309 | { 310 | "cell_type": "markdown", 311 | "metadata": { 312 | "id": "WaNJemIwq419" 313 | }, 314 | "source": [ 315 | "#### Ejercicio:\n", 316 | "\n", 317 | "Ahora, deberías poder crear una lista llamada `clubes_online` que contenga los nombres de los miembros de su club." 318 | ] 319 | }, 320 | { 321 | "cell_type": "code", 322 | "metadata": { 323 | "id": "nMCLlFAerDWG" 324 | }, 325 | "source": [ 326 | "# TODO.\n", 327 | "# Create a new list containing all the names.\n", 328 | "clubes_online = []" 329 | ], 330 | "execution_count": null, 331 | "outputs": [] 332 | }, 333 | { 334 | "cell_type": "markdown", 335 | "metadata": { 336 | "id": "Gz2JkK8DrRIc" 337 | }, 338 | "source": [ 339 | "Ahora agrega dos nuevos estudiantes (puedes inventar sus nombres)." 340 | ] 341 | }, 342 | { 343 | "cell_type": "code", 344 | "metadata": { 345 | "id": "1d-CEterrZL6" 346 | }, 347 | "source": [ 348 | "# TODO.\n", 349 | "# Append two new students called 'Brent' and 'Rodolfo'." 350 | ], 351 | "execution_count": null, 352 | "outputs": [] 353 | }, 354 | { 355 | "cell_type": "markdown", 356 | "metadata": { 357 | "id": "hkoa6UOarhBD" 358 | }, 359 | "source": [ 360 | "## Bucles (ciclos)\n", 361 | "\n", 362 | "**Iteración** significa ejecutar el mismo bloque de código una y otra vez, potencialmente muchas veces. Una estructura de programación que implementa la iteración se llama **bucle** (o **ciclo**).\n", 363 | "\n", 364 | "Hay dos tipos de iteración:\n", 365 | "- **Iteración definida**, en la que el número de repeticiones se especifica explícitamente de antemano\n", 366 | "- **Iteración indefinida**, en la que el bloque de código se ejecuta hasta que se cumple alguna condición\n", 367 | "\n", 368 | "En Python, la iteración indefinida se realiza con un ciclo `while` y la iteración definida se realiza con un ciclo `for`.\n", 369 | "\n", 370 | "### Ciclo `while`\n", 371 | "\n", 372 | "Para un ciclo `while` será importante **establecer una condición de parada**. El formato de un ciclo `while` se muestra a continuación:\n", 373 | "\n", 374 | "```python\n", 375 | "while condition:\n", 376 | " # Code goes ehre!\n", 377 | "```\n", 378 | "\n", 379 | "#### Ejemplo:\n" 380 | ] 381 | }, 382 | { 383 | "cell_type": "code", 384 | "metadata": { 385 | "id": "SSnssdYwqI_G" 386 | }, 387 | "source": [ 388 | "n_interation = 1\n", 389 | "\n", 390 | "while n_iteration <= 10:\n", 391 | " print(f\"Iteration {n_iteration}.\")" 392 | ], 393 | "execution_count": null, 394 | "outputs": [] 395 | }, 396 | { 397 | "cell_type": "markdown", 398 | "metadata": { 399 | "id": "xJFl2lQ1qJak" 400 | }, 401 | "source": [ 402 | "### Ciclo `for`\n", 403 | "\n", 404 | "Python tiene un **ciclo basado en colecciones** o **ciclo basado en iteradores**. Este tipo de bucle itera sobre una colección de objetos, en lugar de especificar valores numéricos o condiciones:\n", 405 | "\n", 406 | "```python\n", 407 | "for i in :\n", 408 | " \n", 409 | "```\n", 410 | "\n", 411 | "#### Ejemplo:\n", 412 | "\n", 413 | "Podemos iterar a través de los elementos de una lista:\n" 414 | ] 415 | }, 416 | { 417 | "cell_type": "code", 418 | "metadata": { 419 | "id": "RFk0YLulqOQW" 420 | }, 421 | "source": [ 422 | "months = [\n", 423 | " 'January',\n", 424 | " 'February',\n", 425 | " 'March',\n", 426 | " 'April',\n", 427 | " 'May',\n", 428 | " 'June',\n", 429 | " 'July',\n", 430 | " 'August',\n", 431 | " 'September',\n", 432 | " 'October',\n", 433 | " 'November',\n", 434 | " 'December',\n", 435 | "]\n", 436 | "\n", 437 | "for month in months:\n", 438 | " print(f\"The current month is {month}.\")" 439 | ], 440 | "execution_count": null, 441 | "outputs": [] 442 | }, 443 | { 444 | "cell_type": "markdown", 445 | "metadata": { 446 | "id": "OHMgj3aavIqc" 447 | }, 448 | "source": [ 449 | "O iterar solo a través de un rango de números:" 450 | ] 451 | }, 452 | { 453 | "cell_type": "code", 454 | "metadata": { 455 | "id": "nevHbKcsvIBa" 456 | }, 457 | "source": [ 458 | "for number in range(10):\n", 459 | " print(f\"The current number is {number}.\")" 460 | ], 461 | "execution_count": null, 462 | "outputs": [] 463 | }, 464 | { 465 | "cell_type": "markdown", 466 | "metadata": { 467 | "id": "7Ko9pJ0_vrnb" 468 | }, 469 | "source": [ 470 | "**Nota:** *¿Todo esto aplica para las tuplas?*\n" 471 | ] 472 | }, 473 | { 474 | "cell_type": "markdown", 475 | "metadata": { 476 | "id": "DZOOUM4jrn5O" 477 | }, 478 | "source": [ 479 | "## Diccionarios\n", 480 | "\n", 481 | "Python proporciona otro tipo de datos compuestos llamado **diccionario**, que es similar a una lista en que es una colección de objetos.\n", 482 | "\n", 483 | "Los diccionarios son diferentes de las listas principalmente por cómo acceder a sus elementos:\n", 484 | "\n", 485 | "- Se accede a los elementos de la lista por su posición en la lista, mediante indexación.\n", 486 | "- Se accede a los elementos del diccionario mediante llaves o claves (pares clave-valor)." 487 | ] 488 | }, 489 | { 490 | "cell_type": "code", 491 | "metadata": { 492 | "id": "FNo_LTSuzEvk" 493 | }, 494 | "source": [ 495 | "student = {\n", 496 | " \"name\": \"Rodolfo Ferro\"\n", 497 | " \"email\": \"ferro@cimat.mx\"\n", 498 | "}" 499 | ], 500 | "execution_count": null, 501 | "outputs": [] 502 | }, 503 | { 504 | "cell_type": "markdown", 505 | "metadata": { 506 | "id": "i6I0b2UkzcJb" 507 | }, 508 | "source": [ 509 | "## Funciones\n", 510 | "\n", 511 | "Las funciones nos permitirán empaquetar código que puede ser invocado a través de una línea con el nombre de la función.\n", 512 | "\n", 513 | "La estructura básica de una función es como sigue:\n", 514 | "\n", 515 | "```python\n", 516 | "def name_of_function(arguments):\n", 517 | " # Code of the function\n", 518 | "\n", 519 | " return something\n", 520 | "```\n", 521 | "\n", 522 | "La nomenclatura de las funciones es consistente con la de las variables." 523 | ] 524 | }, 525 | { 526 | "cell_type": "code", 527 | "metadata": { 528 | "id": "PZTz7Shhrs1M" 529 | }, 530 | "source": [ 531 | "# Implement the 2nd of the Newton's laws of motion\n" 532 | ], 533 | "execution_count": null, 534 | "outputs": [] 535 | }, 536 | { 537 | "cell_type": "markdown", 538 | "metadata": { 539 | "id": "1y8uhVgk0LfN" 540 | }, 541 | "source": [ 542 | "## Módulos y paquetes\n", 543 | "\n", 544 | "Así como hemos estado avanzando, las funciones nos permitirán continuar avanzando en empaquetar aún más algunos blñoques de código, puesto que varias funciones y objetos más robustos pueden escribirse en archivos de código fuente que puede ser _importado_ para uso directo en nuestros programas de día a día.\n", 545 | "\n", 546 | "Un ejemplo de ello es el módulo `random`, que cuenta con funciones para generar números aleatorios y que exploraremos a continuación:" 547 | ] 548 | }, 549 | { 550 | "cell_type": "code", 551 | "metadata": { 552 | "id": "_n-4U4r00RLs" 553 | }, 554 | "source": [ 555 | "" 556 | ], 557 | "execution_count": null, 558 | "outputs": [] 559 | }, 560 | { 561 | "cell_type": "markdown", 562 | "metadata": { 563 | "id": "d0tk7XbG0tnu" 564 | }, 565 | "source": [ 566 | "Una gran ventaja que tiene Python sobre otros lenguajes de programación (y que contribuye a que el lenguaje sea tan utilizado para muchas cosas), es el hecho de que cuenta con una gran comunidad de personas que contribuyen a paquetes robustos para áreas específicas, como cómputo numérico, cómputo cuántico, inteligencia artificial, astrofísica, imagenología biomédica y muchas, muchas cosas más.\n", 567 | "\n", 568 | "En los siguientes dos módulos exploraremos un par con algunos ejemplos y aplicaciones interesantes.\n" 569 | ] 570 | }, 571 | { 572 | "cell_type": "markdown", 573 | "metadata": { 574 | "id": "w7DrerwS1zd_" 575 | }, 576 | "source": [ 577 | "## ¡A resolver el reto!\n", 578 | "\n", 579 | "Vamos a prodecer a crear una lista de diccionarios, esto es, un directorio de estudiantes de Clubes de Ciencia que participarán en una edición en línea.\n", 580 | "\n", 581 | "Cada estudiante debe tener los siguientes atributos:\n", 582 | "- Nombre \n", 583 | "- Edad \n", 584 | "- Temas \n", 585 | "- Menores de edad \n", 586 | "\n", 587 | "Puedes asignar los datos a mano o utilizar funciones aleatorias para llenar los campos." 588 | ] 589 | }, 590 | { 591 | "cell_type": "code", 592 | "metadata": { 593 | "id": "SVynPZKD2RAm" 594 | }, 595 | "source": [ 596 | "# All your code goes here!!!" 597 | ], 598 | "execution_count": null, 599 | "outputs": [] 600 | }, 601 | { 602 | "cell_type": "markdown", 603 | "metadata": { 604 | "id": "efpB7jYb3hQj" 605 | }, 606 | "source": [ 607 | "--------\n", 608 | "\n", 609 | "> Contenido creado por **Rodolfo Ferro** ([CdeCMx](https://clubesdeciencia.mx/) / [Future Lab](https://futurelab.mx/), 2021).
\n", 610 | "> Contacto: [@rodo_ferro](https://www.instagram.com/rodo_ferro/) & [@rodo_ferro](https://twitter.com/rodo_ferro)" 611 | ] 612 | } 613 | ] 614 | } 615 | -------------------------------------------------------------------------------- /B - Intro a NumPy.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "B - Intro a NumPy", 7 | "provenance": [], 8 | "collapsed_sections": [], 9 | "include_colab_link": true 10 | }, 11 | "kernelspec": { 12 | "name": "python3", 13 | "display_name": "Python 3" 14 | } 15 | }, 16 | "cells": [ 17 | { 18 | "cell_type": "markdown", 19 | "metadata": { 20 | "id": "view-in-github", 21 | "colab_type": "text" 22 | }, 23 | "source": [ 24 | "\"Open" 25 | ] 26 | }, 27 | { 28 | "cell_type": "markdown", 29 | "metadata": { 30 | "id": "OpSHrtcJLQEU" 31 | }, 32 | "source": [ 33 | "# Introducción a NumPy\n", 34 | "\n", 35 | "A lo largo de este cuaderno explicaremos algunos elementos básicos y herramientas con las que cuenta NumPy. Los temas específicos que cubriremos en este cuaderno introductorio son los siguientes:\n", 36 | "\n", 37 | "1. Introducción a NumPy\n", 38 | "2. Atributos, tamaño y forma\n", 39 | "3. Creación de arreglos\n", 40 | "4. Indexación y slicing\n", 41 | "5. Operaciones básicas, broadcasting\n", 42 | "6. Valores únicos y cuentas\n", 43 | "7. Matrices en NumPy\n", 44 | "8. Trasposición, aplanamiento y reversa\n", 45 | "9. Reshape de matrices\n", 46 | "10. Módulo random\n", 47 | "11. Módulo de álgebra lineal\n", 48 | "12. Conoce SciPy\n", 49 | "\n", 50 | "### Planteamiento del problema:\n", 51 | "\n", 52 | "El poder manipular datos multidimensionales es generalmente de mucha ayuda, así que utilizaremos algunos de los conceptos previamente mencionados para trabajar con imágenes y descomponerlas en sus diferentes dimensiones (o canales) de color.\n", 53 | "\n", 54 | "## ¿Qué es NumPy?\n", 55 | "\n", 56 | "
\n", 57 | " \n", 58 | "
\n", 59 | "\n", 60 | "**NumPy** es el paquete fundamental para la computación numérica con Python.\n", 61 | "\n", 62 | "De acuerdo con Wikipedia: _\"(...) es una biblioteca para el lenguaje de programación Python que da soporte para crear vectores y matrices grandes multidimensionales, junto con una gran colección de funciones matemáticas de alto nivel para operar con ellas.\"_\n", 63 | "\n", 64 | "\n", 65 | "### Objetos en NumPy\n", 66 | "\n", 67 | "En NumPy, los objetos con los que trabajamos son arreglos multidimensionales:\n", 68 | "\n", 69 | "```\n", 70 | " [1, 2, 3, 4] → [1.0 2.0 3.0 4.0]\n", 71 | "[[1, 2, 3], [4, 5, 6], [7, 8, 9]] → [[1.0 2.0 3.0]\n", 72 | " [4.0 5.0 6.0]\n", 73 | " [7.0 8.0 9.0]]\n", 74 | "```\n", 75 | "\n", 76 | "### ¿Qué es un _array_?\n", 77 | "\n", 78 | "Un arreglo es la formalización de una lista en Python; y un array puede ser indexado por una tupla de enteros no negativos, por booleanos, por otro arreglo o por enteros. El rango de la matriz es el número de dimensiones. La forma de la matriz es una tupla de números enteros que dan el tamaño de la matriz a lo largo de cada dimensión.\n", 79 | "\n", 80 | "Una forma en que podemos inicializar matrices NumPy es a partir de listas de Python, utilizando listas anidadas para datos bidimensionales o de mayor dimensión.\n", 81 | "\n", 82 | "\n" 83 | ] 84 | }, 85 | { 86 | "cell_type": "code", 87 | "metadata": { 88 | "id": "lBy00gJgHaQo" 89 | }, 90 | "source": [ 91 | "import numpy as np # ¡IMPORTANTE!\n", 92 | "\n", 93 | "\n", 94 | "a = np.array([1, 2, 3, 4, 5, 6])\n", 95 | "print(a)\n", 96 | "print(type(a))\n", 97 | "print(a[0])\n", 98 | "print()\n", 99 | "\n", 100 | "b = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])\n", 101 | "print(b)\n", 102 | "print(type(b))\n", 103 | "print(b[0])\n", 104 | "print(type(b[0]))" 105 | ], 106 | "execution_count": null, 107 | "outputs": [] 108 | }, 109 | { 110 | "cell_type": "markdown", 111 | "metadata": { 112 | "id": "RSJW87sPXOAh" 113 | }, 114 | "source": [ 115 | "## Atributos, tamaño y forma\n", 116 | "\n", 117 | "Un arreglo suele ser un contenedor de tamaño fijo de elementos del mismo tipo y tamaño. El número de **dimensiones** y **elementos** se define por su forma. La **forma (shape)** es una tupla de números enteros no negativos que especifican los tamaños de cada dimensión.\n", 118 | "\n", 119 | "En NumPy, las dimensiones se denominan **ejes (axes)**.\n", 120 | "\n", 121 | "Esto significa que si tenemos un arreglo 2D (una matriz) que se ve así:\n", 122 | "\n", 123 | "```python\n", 124 | "[[0., 0., 0.],\n", 125 | " [1., 1., 1.]]\n", 126 | "```\n", 127 | "\n", 128 | "Entonces tenemos 2 ejes. El primer eje tiene una longitud de 2 y el segundo eje tiene una longitud de 3. (`shape=(2, 3)`)\n", 129 | "\n", 130 | "### ¿Cómo saber la forma y tamaño?\n", 131 | "\n", 132 | "- **ndarray.ndim** te dirá el número de ejes o dimensiones de la matriz.\n", 133 | "- **ndarray.size** te dirá el número total de elementos de la matriz. Este es el producto de los elementos de la forma de la matriz.\n", 134 | "- **ndarray.shape** te mostrará una tupla de números que indican el número de elementos almacenados a lo largo de cada dimensión de la matriz.\n", 135 | "\n", 136 | "\n", 137 | "\n" 138 | ] 139 | }, 140 | { 141 | "cell_type": "code", 142 | "metadata": { 143 | "id": "8i5sDqw-XUJP" 144 | }, 145 | "source": [ 146 | "print(b)\n", 147 | "print(b.ndim)\n", 148 | "print(b.size)\n", 149 | "print(b.shape)" 150 | ], 151 | "execution_count": null, 152 | "outputs": [] 153 | }, 154 | { 155 | "cell_type": "markdown", 156 | "metadata": { 157 | "id": "nlMAcIGEYIef" 158 | }, 159 | "source": [ 160 | "## Creación de arreglos\n", 161 | "\n", 162 | "Además de crear un array a partir de una secuencia de elementos, puedes crear uno llena de ceros, o llena de unos:\n", 163 | "\n", 164 | "```python\n", 165 | "np.zeros(2)\n", 166 | "# array([0., 0.])\n", 167 | "np.ones(2)\n", 168 | "# array([1., 1.])\n", 169 | "```\n", 170 | "\n", 171 | "#### Ejercicio:\n", 172 | "\n", 173 | "- Crea una matriz de ceros de 5x5 e imprímela en pantalla.\n", 174 | "- ¿Puedes crear una matriz identidad? Una matriz identidad es una matriz cuadrada llena de ceros y con unos en la diagonal. Puedes construirla utilizando un ciclo `for` y haciendo uso de los que conocemos hasta ahora para iterar listas en Python.\n", 175 | "- Si quieres construir una matriz identidad, también puedes utilizar la función `np.eye()`." 176 | ] 177 | }, 178 | { 179 | "cell_type": "code", 180 | "metadata": { 181 | "id": "RmbbjQIqYT6i" 182 | }, 183 | "source": [ 184 | "# TODO.\n" 185 | ], 186 | "execution_count": null, 187 | "outputs": [] 188 | }, 189 | { 190 | "cell_type": "markdown", 191 | "metadata": { 192 | "id": "bwPAwu74G3mk" 193 | }, 194 | "source": [ 195 | "También puedes usar np.linspace() para crear una matriz con valores espaciados linealmente en un intervalo especificado.\n", 196 | "\n", 197 | "Para esto nos apoyaremos de una biblioteca que nos permite graficar." 198 | ] 199 | }, 200 | { 201 | "cell_type": "code", 202 | "metadata": { 203 | "id": "M8LbAUGmG8RV" 204 | }, 205 | "source": [ 206 | "x = np.linspace(0, 50, 51)\n", 207 | "print(x)\n", 208 | "\n", 209 | "y = np.sin(x)\n", 210 | "print(y)" 211 | ], 212 | "execution_count": null, 213 | "outputs": [] 214 | }, 215 | { 216 | "cell_type": "code", 217 | "metadata": { 218 | "id": "9RmTn2xEHTxu" 219 | }, 220 | "source": [ 221 | "import matplotlib.pyplot as plt\n", 222 | "plt.style.use('seaborn')\n", 223 | "\n", 224 | "\n", 225 | "fig = plt.figure(figsize=(20, 5))\n", 226 | "plt.plot(x, y)\n", 227 | "plt.show()" 228 | ], 229 | "execution_count": null, 230 | "outputs": [] 231 | }, 232 | { 233 | "cell_type": "markdown", 234 | "metadata": { 235 | "id": "jLwEXaMvIUag" 236 | }, 237 | "source": [ 238 | "## Indexación y slicing\n", 239 | "\n", 240 | "Podemos indexar y usar slicing matrices NumPy de la misma manera que hacemos con listas de Python.\n", 241 | "\n", 242 | "```python\n", 243 | "data = np.array([1, 2, 3])\n", 244 | "\n", 245 | "print(data[1])\n", 246 | "# 2\n", 247 | "print(data[0:2])\n", 248 | "# array([1, 2])\n", 249 | "print(data[1:])\n", 250 | "# array([2, 3])\n", 251 | "print(data[-2:])\n", 252 | "# array([2, 3])\n", 253 | "```\n", 254 | "\n", 255 | "La principal diferencia es que en lugar de usar múltiples corchetes, usamos comas para acceder a elementos. Exploremos en un ejemplo:\n" 256 | ] 257 | }, 258 | { 259 | "cell_type": "code", 260 | "metadata": { 261 | "id": "Bded7lCiI81o" 262 | }, 263 | "source": [ 264 | "print(b)\n", 265 | "print(b[0])" 266 | ], 267 | "execution_count": null, 268 | "outputs": [] 269 | }, 270 | { 271 | "cell_type": "markdown", 272 | "metadata": { 273 | "id": "kV1KnLUxIXcC" 274 | }, 275 | "source": [ 276 | "## Operaciones básicas, broadcasting\n", 277 | "\n", 278 | "Si tuviésemos un par de arrays del misma forma, podríamos operar entre ellos. Consideremos el par de arreglos a continuación:\n", 279 | "\n", 280 | "
\n", 281 | " \n", 282 | "
\n", 283 | "\n", 284 | "Podríamos sumarlos:\n", 285 | "\n", 286 | "
\n", 287 | " \n", 288 | "
" 289 | ] 290 | }, 291 | { 292 | "cell_type": "code", 293 | "metadata": { 294 | "id": "ZVe_biZZ_z2j" 295 | }, 296 | "source": [ 297 | "data = np.array([1, 2])\n", 298 | "ones = np.ones(2, dtype=int)\n", 299 | "print(data + ones)" 300 | ], 301 | "execution_count": null, 302 | "outputs": [] 303 | }, 304 | { 305 | "cell_type": "markdown", 306 | "metadata": { 307 | "id": "I2D4JbZY_2bb" 308 | }, 309 | "source": [ 310 | "\n", 311 | "Esto en general se preserva para las otras operaciones básicas:\n", 312 | "\n", 313 | "
\n", 314 | " \n", 315 | "
\n", 316 | "\n" 317 | ] 318 | }, 319 | { 320 | "cell_type": "code", 321 | "metadata": { 322 | "id": "Ri61t6Tb_8T6" 323 | }, 324 | "source": [ 325 | "print(data - ones)\n", 326 | "print(data * data)\n", 327 | "print(data / data)" 328 | ], 329 | "execution_count": null, 330 | "outputs": [] 331 | }, 332 | { 333 | "cell_type": "markdown", 334 | "metadata": { 335 | "id": "WsluyIZjAFZT" 336 | }, 337 | "source": [ 338 | "#### ¿Qué sucede si queremos una multiplicación escalar?\n", 339 | "\n", 340 | "## Broadcasting\n", 341 | "\n", 342 | "
\n", 343 | " \n", 344 | "
" 345 | ] 346 | }, 347 | { 348 | "cell_type": "code", 349 | "metadata": { 350 | "id": "KWVlvxGAAXB1" 351 | }, 352 | "source": [ 353 | "data = np.array([1.0, 2.0])\n", 354 | "data * 1.6" 355 | ], 356 | "execution_count": null, 357 | "outputs": [] 358 | }, 359 | { 360 | "cell_type": "markdown", 361 | "metadata": { 362 | "id": "tsLLRJaSIe8z" 363 | }, 364 | "source": [ 365 | "## Valores únicos y cuentas\n", 366 | "\n", 367 | "Existen algunas funciones propias de los arreglos en NumPy:\n", 368 | "- **.max()** te dirá el máximo de los elementos del arreglo.\n", 369 | "- **.min()** te dirá el mínimo de los elementos del arreglo.\n", 370 | "- **.sum()** te dirá la suma de los elementos del arreglo.\n", 371 | "- **.prod()** te dirá el producto de los elementos del arreglo.\n", 372 | "\n" 373 | ] 374 | }, 375 | { 376 | "cell_type": "code", 377 | "metadata": { 378 | "id": "gPn2pn6SAnGn" 379 | }, 380 | "source": [ 381 | "A = np.array([\n", 382 | " [45, 21, 9, 92],\n", 383 | " [76, 2, 12, 35],\n", 384 | " [23, 47, 89, 25],\n", 385 | " [40, 78, 23, 1]\n", 386 | "])" 387 | ], 388 | "execution_count": null, 389 | "outputs": [] 390 | }, 391 | { 392 | "cell_type": "markdown", 393 | "metadata": { 394 | "id": "pOoMtzsPAqex" 395 | }, 396 | "source": [ 397 | "Incluso existen funciones que te devuelven estadísticos de tus datos:\n", 398 | "- **.mean()** te dirá el promedio de los elementos del arreglo.\n", 399 | "- **.std()** te dirá la desviación estándar de los elementos del arreglo.\n" 400 | ] 401 | }, 402 | { 403 | "cell_type": "code", 404 | "metadata": { 405 | "id": "A53zvTz3Cha-" 406 | }, 407 | "source": [ 408 | "B = np.array([45, 21, 9, 92, 76, 2, 12, 35, 23, 47, 89, 25, 40, 78, 23, 1])" 409 | ], 410 | "execution_count": null, 411 | "outputs": [] 412 | }, 413 | { 414 | "cell_type": "markdown", 415 | "metadata": { 416 | "id": "1yuwUeEbDKC9" 417 | }, 418 | "source": [ 419 | "En cuanto a querer devolver valores únicos, podemos usar **.uniques()**" 420 | ] 421 | }, 422 | { 423 | "cell_type": "code", 424 | "metadata": { 425 | "id": "97nXosvRDNZ8" 426 | }, 427 | "source": [ 428 | "a = np.array([11, 11, 12, 13, 14, 15, 16, 17, 12, 13, 11, 14, 18])\n", 429 | "unique_values = np.unique(a)\n", 430 | "print(unique_values)" 431 | ], 432 | "execution_count": null, 433 | "outputs": [] 434 | }, 435 | { 436 | "cell_type": "markdown", 437 | "metadata": { 438 | "id": "zi0aCgz8str7" 439 | }, 440 | "source": [ 441 | "Finalmente, no hay que olvidar que podemos utilizar operaciones matemáticas básicas:\n", 442 | "- **np.sin(x)** te devolverá el seno del vector `x`.\n", 443 | "- **np.cos(x)** te devolverá el coseno del vector `x`\n", 444 | "- Etcétera." 445 | ] 446 | }, 447 | { 448 | "cell_type": "code", 449 | "metadata": { 450 | "id": "OZBPb1Eus1xl" 451 | }, 452 | "source": [ 453 | "np.cos(B)" 454 | ], 455 | "execution_count": null, 456 | "outputs": [] 457 | }, 458 | { 459 | "cell_type": "markdown", 460 | "metadata": { 461 | "id": "8pZnR-8yIimm" 462 | }, 463 | "source": [ 464 | "## Trasposición, aplanamiento y reversa\n", 465 | "\n", 466 | "Es común tener que trasponer matrices. Las matrices NumPy tienen la propiedad **.T** que permite transponer una matriz. De igual manera se puede utilizar **.transpose()**\n", 467 | "\n", 468 | "
\n", 469 | " \n", 470 | "
\n" 471 | ] 472 | }, 473 | { 474 | "cell_type": "code", 475 | "metadata": { 476 | "id": "7EpMdUEaIZ9A" 477 | }, 478 | "source": [ 479 | "print(A)" 480 | ], 481 | "execution_count": null, 482 | "outputs": [] 483 | }, 484 | { 485 | "cell_type": "markdown", 486 | "metadata": { 487 | "id": "xZU8i5oRIaTO" 488 | }, 489 | "source": [ 490 | "En algunas ocasiones resulta útil aplanar una matriz, esto es, convertirla en un arreglo unidimensional. Esto puede lograrse con **.flatten()**\n" 491 | ] 492 | }, 493 | { 494 | "cell_type": "code", 495 | "metadata": { 496 | "id": "xwwIkx3NIgJm" 497 | }, 498 | "source": [ 499 | "print(A)" 500 | ], 501 | "execution_count": null, 502 | "outputs": [] 503 | }, 504 | { 505 | "cell_type": "markdown", 506 | "metadata": { 507 | "id": "qQgZOKbEIp1x" 508 | }, 509 | "source": [ 510 | "Al igual que con las listas en Python, podemos utilizar slicing para revertir un array, sin embargo, NumPy tiene una función propia: **np.flip()**\n", 511 | "\n", 512 | "#### ¿Qué sucede si lo utilizamos en matrices?\n" 513 | ] 514 | }, 515 | { 516 | "cell_type": "code", 517 | "metadata": { 518 | "id": "UgLp-wEFIuzk" 519 | }, 520 | "source": [ 521 | "arr = np.array([1, 2, 3, 4, 5, 6, 7, 8])\n", 522 | "reversed_arr = np.flip(arr)\n", 523 | "print('Reversed Array: ', reversed_arr)" 524 | ], 525 | "execution_count": null, 526 | "outputs": [] 527 | }, 528 | { 529 | "cell_type": "code", 530 | "metadata": { 531 | "id": "BQ4ilZ87IyzA" 532 | }, 533 | "source": [ 534 | "print(A)" 535 | ], 536 | "execution_count": null, 537 | "outputs": [] 538 | }, 539 | { 540 | "cell_type": "markdown", 541 | "metadata": { 542 | "id": "zE2LrEWCI2D4" 543 | }, 544 | "source": [ 545 | "### Reshape de matrices\n", 546 | "\n", 547 | "**.reshape()** permite cambiar la forma de una matriz sin cambiar los datos. Sólo ten presente que cuando usamos esta función, la matriz que queremos producir debe tener la misma cantidad de elementos que la matriz original.\n" 548 | ] 549 | }, 550 | { 551 | "cell_type": "code", 552 | "metadata": { 553 | "id": "1ktO4FSzI6Vt" 554 | }, 555 | "source": [ 556 | "print(A)" 557 | ], 558 | "execution_count": null, 559 | "outputs": [] 560 | }, 561 | { 562 | "cell_type": "markdown", 563 | "metadata": { 564 | "id": "h3PJ_8rAIg5o" 565 | }, 566 | "source": [ 567 | "## Matrices en NumPy\n", 568 | "\n", 569 | "Procederemos a explorar un poco con una imagen y sus canales de color.\n" 570 | ] 571 | }, 572 | { 573 | "cell_type": "code", 574 | "metadata": { 575 | "id": "KHDCUPjMKTZp" 576 | }, 577 | "source": [ 578 | "import urllib.request\n", 579 | "\n", 580 | "\n", 581 | "image_url = 'https://raw.githubusercontent.com/futurelabmx/cdecmx/gh-pages/assets/images/cdec_python.jpeg'\n", 582 | "filename = 'image.jgp'\n", 583 | "urllib.request.urlretrieve(image_url, filename)" 584 | ], 585 | "execution_count": null, 586 | "outputs": [] 587 | }, 588 | { 589 | "cell_type": "code", 590 | "metadata": { 591 | "id": "bCykkl7sJTf6" 592 | }, 593 | "source": [ 594 | "import matplotlib.pyplot as plt\n", 595 | "import numpy as np\n" 596 | ], 597 | "execution_count": null, 598 | "outputs": [] 599 | }, 600 | { 601 | "cell_type": "code", 602 | "metadata": { 603 | "id": "BVKbcMnhJNzQ" 604 | }, 605 | "source": [ 606 | "# Sección de código libre" 607 | ], 608 | "execution_count": null, 609 | "outputs": [] 610 | }, 611 | { 612 | "cell_type": "markdown", 613 | "metadata": { 614 | "id": "AOLl3XB1IkPj" 615 | }, 616 | "source": [ 617 | "## Módulo random\n", 618 | "\n", 619 | "Conoce más del módulo `random` aquí: https://numpy.org/doc/stable/reference/random/" 620 | ] 621 | }, 622 | { 623 | "cell_type": "code", 624 | "metadata": { 625 | "id": "sLJQyPf0JYyY" 626 | }, 627 | "source": [ 628 | "import matplotlib.pyplot as plt\n", 629 | "import numpy as np" 630 | ], 631 | "execution_count": null, 632 | "outputs": [] 633 | }, 634 | { 635 | "cell_type": "markdown", 636 | "metadata": { 637 | "id": "LSRnPmH_ImOn" 638 | }, 639 | "source": [ 640 | "## Módulo de álgebra lineal\n", 641 | "\n", 642 | "Conoce más del módulo `linalg` aquí: https://numpy.org/doc/stable/reference/routines.linalg" 643 | ] 644 | }, 645 | { 646 | "cell_type": "markdown", 647 | "metadata": { 648 | "id": "a0EhYE0pIobA" 649 | }, 650 | "source": [ 651 | "## Conoce SciPy\n", 652 | "\n", 653 | "Explora SciPy aquí: https://www.scipy.org/" 654 | ] 655 | }, 656 | { 657 | "cell_type": "markdown", 658 | "metadata": { 659 | "id": "efpB7jYb3hQj" 660 | }, 661 | "source": [ 662 | "--------\n", 663 | "\n", 664 | "> Contenido creado por **Rodolfo Ferro** ([CdeCMx](https://clubesdeciencia.mx/) / [Future Lab](https://futurelab.mx/), 2021).
\n", 665 | "> Contacto: [@rodo_ferro](https://www.instagram.com/rodo_ferro/) & [@rodo_ferro](https://twitter.com/rodo_ferro)" 666 | ] 667 | } 668 | ] 669 | } 670 | -------------------------------------------------------------------------------- /C - Intro a Pandas.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "C - Intro a Pandas", 7 | "provenance": [], 8 | "collapsed_sections": [], 9 | "authorship_tag": "ABX9TyN1uyubti2jv5tTwCvc6uKI", 10 | "include_colab_link": true 11 | }, 12 | "kernelspec": { 13 | "name": "python3", 14 | "display_name": "Python 3" 15 | }, 16 | "language_info": { 17 | "name": "python" 18 | } 19 | }, 20 | "cells": [ 21 | { 22 | "cell_type": "markdown", 23 | "metadata": { 24 | "id": "view-in-github", 25 | "colab_type": "text" 26 | }, 27 | "source": [ 28 | "\"Open" 29 | ] 30 | }, 31 | { 32 | "cell_type": "markdown", 33 | "metadata": { 34 | "id": "V1kR35Lr95Lu" 35 | }, 36 | "source": [ 37 | "# Introducción a Pandas.\n", 38 | " \n", 39 | "En este cuaderno veremos los elementos y funciones básicas de la librería **Pandas**. Los contenidos específicos son:\n", 40 | " \n", 41 | "1. Introducción a Pandas.\n", 42 | "2. Dónde encontrar datos.\n", 43 | "3. Carga de datos de diferentes formatos.\n", 44 | "4. Series y DataFrames.\n", 45 | "5. Revisando los datos.\n", 46 | "6. Selección de datos por etiqueta.\n", 47 | "7. Selección de datos por posición.\n", 48 | "8. Operaciones básicas: Estadísticos.\n", 49 | "9. Operaciones básicas: Apply.\n", 50 | "10. Unión de datos: Concatenación.\n", 51 | " \n", 52 | "### Planteamiento del problema:\n", 53 | " \n", 54 | "Limpiar, analizar y obtener información de un conjunto de datos tabulados es útil al tratar de **obtener conocimiento** de la información que tenemos. Utilizaremos lo aprendido en este módulo para analizar tres datasets distintos. \n", 55 | " \n", 56 | "## ¿Qué es Pandas? \n", 57 | " \n", 58 | "
\n", 59 | " \n", 60 | "
\n", 61 | " \n", 62 | "**Pandas** es una librería de Python con la que puedes trabajar con datos tabulados. Es muy útil para limpiar, analizar y procesar datos.\n", 63 | " \n", 64 | "De acuerdo con Wikipedia: _\"(...) es una biblioteca de software escrita como extensión de **NumPy** para manipulación y análisis de datos para el lenguaje de programación Python. En particular, ofrece estructuras de datos y operaciones para manipular tablas numéricas y series temporales.\"_\n", 65 | " \n", 66 | "### Objetos en Pandas.\n", 67 | " \n", 68 | "En Pandas, los objetos con los que trabajaremos son dos: **DataFrames** y Series. Un DataFrame lo puedes entender como un **tabla** (como las de Excel), y una **Series** como una **tabla con una sola columna**. Más adelante veremos mas a detalle a estos dos objetos que son los objetos base de Pandas." 69 | ] 70 | }, 71 | { 72 | "cell_type": "code", 73 | "metadata": { 74 | "id": "stnODbMd-EI3" 75 | }, 76 | "source": [ 77 | "# Importamos el módulo que aprenderemos en este módulo :)\n", 78 | "import pandas as pd\n", 79 | "\n", 80 | "# También usaremos un poco Numpy\n", 81 | "import numpy as np" 82 | ], 83 | "execution_count": null, 84 | "outputs": [] 85 | }, 86 | { 87 | "cell_type": "markdown", 88 | "metadata": { 89 | "id": "tjXN3eJuM44K" 90 | }, 91 | "source": [ 92 | "## ¿Dónde encontrar datos?\n", 93 | " \n", 94 | "En internet existen repositorios de **datos abiertos** de los que puedes descargar datasets, jugar con ellos, analizarlos y aprender. Algunos ejemplos:\n", 95 | " \n", 96 | "1. [Kaggle](https://www.kaggle.com/datasets): Sitio web para prácticar y aprender sobre **ciencia de datos y machine learning**. Además de los datasets que hay en el sitio, ¡puedes correr notebooks como este!. Los dataset están por lo general explicados y listos para usarse.\n", 97 | "2. [UC Irvine Machine Learning Repository](http://archive.ics.uci.edu/ml/index.php): En este repositorio hay más de **500 datasets** de diversos temas. Usualmente son útiles para practicar y aprender sobre machine learning.\n", 98 | "3. [Datos Abiertos de México](https://datos.gob.mx/): En este sitio web se encuentra una recopilación de datos abiertos de diversas instituciones, así como del **gobierno federal y gobiernos estatales**. \n", 99 | "4. [INEGI](https://www.inegi.org.mx/datos/): Datos obtenidos de los diversos **censos** que realiza el Instituto Nacional de Estadística y Geografía.\n", 100 | " \n", 101 | "Incluso puedes encontrar **datos abiertos de ciencia**: \n", 102 | "1. [CERN Opendata](https://opendata.cern.ch/): Más de dos petabytes de datos de **física de partículas**.\n", 103 | "2. [NASA Open Data Portal](https://data.nasa.gov/): Datos aeroespaciales, de ciencias de la tierra... **¡Muchos datos!**✨\n", 104 | " \n", 105 | "Esta no es una lista exhaustiva, hay muchos más recursos disponibles con los que puedes trabajar.\n" 106 | ] 107 | }, 108 | { 109 | "cell_type": "markdown", 110 | "metadata": { 111 | "id": "mA84olu4M5fG" 112 | }, 113 | "source": [ 114 | "## Carga de datos de diferentes formatos.\n", 115 | " \n", 116 | "Con Pandas puedes **cargar datos** de archivos externos, los cuales pueden estar en internet o en tu computadora (quizá bajaste alguna de las páginas de arriba 👀). Por lo general se utilizan datos tabulados (tablas) en Pandas, y los tipos de archivos desde los que puedes cargar datos son varios. Los más comunes son archivos con _valores separados por comas_ o CSV, por sus siglas en inglés, con extensión **.csv** y archivos de Excel con extensión **.xlsx**.\n", 117 | " \n", 118 | " \n", 119 | "```python\n", 120 | "# Para importar un archivo csv\n", 121 | "datos = read_csv('nombre_del_archivo.csv')\n", 122 | " \n", 123 | "# Para importar un archivo de excel\n", 124 | "datos = read_excel('nombre_del_archivo.xlsx') \n", 125 | "```\n", 126 | " \n", 127 | "
\n", 128 | " \n", 129 | "
\n", 130 | " \n", 131 | "Hay más tipos de archivos válidos, como **.html** o **.json** y se importan al igual que los ejemplos anteriores. De la misma manera en la que cargamos datos, podemos guardar un DataFrame o una Series en un archivo con extensión válida: \n", 132 | " \n", 133 | "```python\n", 134 | "# Guardamos los datos en un archivo CSV\n", 135 | "datos.to_csv('datos_guardados.csv')\n", 136 | "```\n", 137 | "Ahora, cargaremos tres datasets que usaremos más adelante. Este primer dataset viene de: _Kaggle_, [Titanic - Machine Learning from Disaster](https://www.kaggle.com/c/titanic/data). El dataset describe información de personas que viajaban en el Titanic." 138 | ] 139 | }, 140 | { 141 | "cell_type": "code", 142 | "metadata": { 143 | "id": "HbgjsCkOGEfE" 144 | }, 145 | "source": [ 146 | "# Importamos un archivo de Excel que está en un repositorio en GitHub\n", 147 | "df_titanic = pd.read_excel('https://raw.githubusercontent.com/GabrielMissael/'+\n", 148 | " 'cdecmx/gh-pages/assets/datasets/Titanic.xlsx')\n", 149 | " \n", 150 | "# Podemos ver el inicio de un DataFrame con .head()\n", 151 | "df_titanic.head()" 152 | ], 153 | "execution_count": null, 154 | "outputs": [] 155 | }, 156 | { 157 | "cell_type": "markdown", 158 | "metadata": { 159 | "id": "pVScM7QNZjES" 160 | }, 161 | "source": [ 162 | "El siguiente dataset viene de muestra dentro de Google Colab, y describe información poblacional e inmobiliaria de California." 163 | ] 164 | }, 165 | { 166 | "cell_type": "code", 167 | "metadata": { 168 | "id": "aT4-WQF1M5ly" 169 | }, 170 | "source": [ 171 | "# Importamos un archivo CSV que viene de ejemplo en Google Colab\n", 172 | "df_casas = pd.read_csv('sample_data/california_housing_test.csv')\n", 173 | "df_casas.head()" 174 | ], 175 | "execution_count": null, 176 | "outputs": [] 177 | }, 178 | { 179 | "cell_type": "markdown", 180 | "metadata": { 181 | "id": "_J03hiE8_rWH" 182 | }, 183 | "source": [ 184 | "Finalmente, datos de: [Wikipedia - World population](https://en.wikipedia.org/wiki/World_population), sobre los 10 países más densamente poblados en el mundo." 185 | ] 186 | }, 187 | { 188 | "cell_type": "code", 189 | "metadata": { 190 | "id": "a_dkw4kJ-jzm" 191 | }, 192 | "source": [ 193 | "# Podemos importar tablas que estén en páginas Web como wikipedia\n", 194 | "tabla_poblacion = pd.read_html('https://en.wikipedia.org/wiki/World_population', \n", 195 | " match = '10 most densely populated countries')\n", 196 | "\n", 197 | "df_poblacion = tabla_poblacion[0].set_index('Country')\n", 198 | "df_poblacion" 199 | ], 200 | "execution_count": null, 201 | "outputs": [] 202 | }, 203 | { 204 | "cell_type": "markdown", 205 | "metadata": { 206 | "id": "orngfmWGaZHu" 207 | }, 208 | "source": [ 209 | "## Series y DataFrames.\n", 210 | " \n", 211 | "Como ya mencionamos, una Series se puede entender como una **tabla con una sola columna**, aunque también puedes verla como una lista donde cada elemento tiene una etiqueta, un **índice** el cual por default es un número entero de la posición del elemento.\n", 212 | " \n", 213 | "
\n", 214 | " \n", 215 | "
\n", 216 | "Para crear una serie partiendo de una lista:\n" 217 | ] 218 | }, 219 | { 220 | "cell_type": "code", 221 | "metadata": { 222 | "id": "-JBIpGSVM5zQ" 223 | }, 224 | "source": [ 225 | "serie = pd.Series(['Hola', 3.1416, 'A'])\n", 226 | "\n", 227 | "# Imprimimos la serie que creamos\n", 228 | "print(serie)\n", 229 | "\n", 230 | "# Información de la serie\n", 231 | "print(\"\\nTipo de dato: \", type(serie))\n", 232 | "print(\"Tamaño: \", serie.size)" 233 | ], 234 | "execution_count": null, 235 | "outputs": [] 236 | }, 237 | { 238 | "cell_type": "markdown", 239 | "metadata": { 240 | "id": "fhhAhDF5bMM3" 241 | }, 242 | "source": [ 243 | "Observamos cómo cada elemento de la lista ahora tiene un índice. Podemos especificar el índice explícitamente: " 244 | ] 245 | }, 246 | { 247 | "cell_type": "code", 248 | "metadata": { 249 | "id": "K10hkWJrbWmq" 250 | }, 251 | "source": [ 252 | "serie = pd.Series(data = ['Aaa', 'Bbb', 'Ccc'], \n", 253 | " index = ['Elemento 1', 'Elemento 2', 'Elemento 2'])\n", 254 | " \n", 255 | "print(serie)\n", 256 | " \n", 257 | "# Podemos obtener un elemento con su índice\n", 258 | "print(serie['Elemento 1'])\n" 259 | ], 260 | "execution_count": null, 261 | "outputs": [] 262 | }, 263 | { 264 | "cell_type": "markdown", 265 | "metadata": { 266 | "id": "dwkmLggUM5sO" 267 | }, 268 | "source": [ 269 | "Los **DataFrames** son más complejos que las Series, ya que ahora tenemos una **tabla con varias columnas**. En este caso, tendremos **índices** para cada fila y también etiquetas para las **columnas**. Los valores default son también enteros que indican la posición.\n", 270 | " \n", 271 | "
\n", 272 | " \n", 273 | "
\n" 274 | ] 275 | }, 276 | { 277 | "cell_type": "code", 278 | "metadata": { 279 | "id": "UQgL3uU8fExw" 280 | }, 281 | "source": [ 282 | "# Creemos DataFrame con una matriz aleatoria.\n", 283 | "df = pd.DataFrame(data = np.random.rand(3, 4))\n", 284 | " \n", 285 | "print(\"Tipo: \", type(df)) # Tipo de objeto\n", 286 | "print(\"Tamaño: \", df.size) #El tamaño es igual al número de celdas\n", 287 | "df # Visualizamos el DataFrame completo" 288 | ], 289 | "execution_count": null, 290 | "outputs": [] 291 | }, 292 | { 293 | "cell_type": "code", 294 | "metadata": { 295 | "id": "fnM6Ual-lcWS" 296 | }, 297 | "source": [ 298 | "# Podemos crear DataFrames a partir de diccionarios CUADRADOS\n", 299 | "df_dict = pd.DataFrame({\n", 300 | " 'Nombre':['Juan', 'María', 'Guadalupe'],\n", 301 | " 'Edad':[18, 22, 34],\n", 302 | " 'Altura':[1.73, 1.80, 1.50],}, \n", 303 | " index = ['Persona 1', 'Persona 2', 'Persona 3']) # Especificamos índice\n", 304 | "df_dict" 305 | ], 306 | "execution_count": null, 307 | "outputs": [] 308 | }, 309 | { 310 | "cell_type": "markdown", 311 | "metadata": { 312 | "id": "W73BhXXoysU6" 313 | }, 314 | "source": [ 315 | "Ejercicio: \n", 316 | "- Crea un DataFrame con una matriz de ceros con dimensión (5, 4)\n", 317 | "- Asigna números enteros pares como índice.\n", 318 | "- Asigna letras como columnas." 319 | ] 320 | }, 321 | { 322 | "cell_type": "code", 323 | "metadata": { 324 | "id": "yUwaSH-dy84q" 325 | }, 326 | "source": [ 327 | "# To-Do\n" 328 | ], 329 | "execution_count": null, 330 | "outputs": [] 331 | }, 332 | { 333 | "cell_type": "markdown", 334 | "metadata": { 335 | "id": "Ovp65auHM55T" 336 | }, 337 | "source": [ 338 | "## Revisando los datos.\n", 339 | " \n", 340 | "Para visualizar los datos de un DataFrame, tenemos dos opciones:\n", 341 | " \n", 342 | "```python\n", 343 | "# Mostramos las primeras 7 filas.\n", 344 | "df.head(n = 7)\n", 345 | " \n", 346 | "# Mostramos las últimas 4 filas.\n", 347 | "df.tail(n = 4)\n", 348 | "```\n", 349 | "Si queremos ver un DataFrame completo, lo ponemos solo en una celda.\n", 350 | " \n", 351 | "```python\n", 352 | "# Para ver todo el DataFrame\n", 353 | "df\n", 354 | "```\n", 355 | "Si el DataFrame es muy grande, no se podrá visualizar completo. Veamos los primeros tres y los últimos cuatro elementos del DataFrame de los datos que cargamos del Titanic.\n" 356 | ] 357 | }, 358 | { 359 | "cell_type": "code", 360 | "metadata": { 361 | "id": "xn3YfBSlM5_s" 362 | }, 363 | "source": [ 364 | "df_titanic.head(n = 3)" 365 | ], 366 | "execution_count": null, 367 | "outputs": [] 368 | }, 369 | { 370 | "cell_type": "code", 371 | "metadata": { 372 | "id": "rV_TP6dUon5J" 373 | }, 374 | "source": [ 375 | "df_titanic.tail(n = 4)" 376 | ], 377 | "execution_count": null, 378 | "outputs": [] 379 | }, 380 | { 381 | "cell_type": "markdown", 382 | "metadata": { 383 | "id": "SG3-VF49tzAT" 384 | }, 385 | "source": [ 386 | "Además de consultar partes del DataFrame, también podemos consultar las etiquetas en las **filas** y las **columnas**, así como todos los **valores** del DataFrame.\n", 387 | " \n", 388 | "```python\n", 389 | "columnas = df.columns # Obtenemos columnas\n", 390 | "indice = df.index # Obtenemos filas\n", 391 | "valores = df.values # Obtenemos valores\n", 392 | "```\n", 393 | "Veamos un ejemplo de esto:\n" 394 | ] 395 | }, 396 | { 397 | "cell_type": "code", 398 | "metadata": { 399 | "id": "BJQX6Su5uc55" 400 | }, 401 | "source": [ 402 | "columnas = df_dict.columns\n", 403 | "filas = df_dict.index\n", 404 | "valores = df_dict.values\n", 405 | "\n", 406 | "print('Columnas: ', columnas, '\\nFilas: ', filas)\n", 407 | "print(valores, type(valores)) # Los valores son una matriz de NumPy!!\n", 408 | "\n", 409 | "df_dict # Recordamos el DataFrame de donde obtenemos estos valores" 410 | ], 411 | "execution_count": null, 412 | "outputs": [] 413 | }, 414 | { 415 | "cell_type": "markdown", 416 | "metadata": { 417 | "id": "7zzgbT7B0Qo9" 418 | }, 419 | "source": [ 420 | "Finalmente, cuando tenemos un conjunto de datos, nos será útil hacer un análisis inicial (exploratorio) de los datos. Si consideramos que en las columnas tenemos **variables** y en las filas distintos registros de estas, podemos obtener valores de interés con: \n", 421 | " \n", 422 | "```python\n", 423 | "# Describimos en general el DataFrame\n", 424 | "df.describe()\n", 425 | "```\n", 426 | "Por ejemplo, obtenemos una descripción del DataFrame de la densidad poblacional:\n" 427 | ] 428 | }, 429 | { 430 | "cell_type": "code", 431 | "metadata": { 432 | "id": "GKrr4_3T0Pgo" 433 | }, 434 | "source": [ 435 | "df_poblacion.describe()" 436 | ], 437 | "execution_count": null, 438 | "outputs": [] 439 | }, 440 | { 441 | "cell_type": "markdown", 442 | "metadata": { 443 | "id": "4KCcaNPmI96x" 444 | }, 445 | "source": [ 446 | "Obtenemos valores de interés de las variables, como el valor máximo, valor mínimo, media, etc. Pero, ¿qué pasa si tenemos las variables en las filas?. Podemos **trasponer** el DataFrame, de manera similar a lo que se hizo en el módulo de NumPy:\n", 447 | " \n", 448 | "```python\n", 449 | "# Trasponemos un dataframe y guardamos el resultado\n", 450 | "df_traspuesto = df.T\n", 451 | "```\n", 452 | "Por ejemplo:\n" 453 | ] 454 | }, 455 | { 456 | "cell_type": "code", 457 | "metadata": { 458 | "id": "yxKmkK6NJwnD" 459 | }, 460 | "source": [ 461 | "df_poblacion_traspuesto = df_poblacion.T\n", 462 | "df_poblacion_traspuesto" 463 | ], 464 | "execution_count": null, 465 | "outputs": [] 466 | }, 467 | { 468 | "cell_type": "markdown", 469 | "metadata": { 470 | "id": "KtzwM_0AM6GG" 471 | }, 472 | "source": [ 473 | "## Selección de datos por etiqueta.\n", 474 | " \n", 475 | "Podemos seleccionar una o varias **columnas** específicas de un DataFrame utilizando las etiquetas. Se crea un nuevo **DataFrame** con las columnas especificadas. \n", 476 | " \n", 477 | "
\n", 478 | " \n", 479 | "
\n", 480 | " \n", 481 | "De manera similar, podemos seleccionar **filas** utilizando el índice. Podemos seleccionar una o varias filas y se crea también un nuevo **DataFrame**\n", 482 | " \n", 483 | "
\n", 484 | " \n", 485 | "
\n", 486 | " \n", 487 | "Para seleccionar utilizando las **etiquetas** (nombres de filas y columnas) usamos el método **loc()**. Funciona como sigue:\n", 488 | " \n", 489 | "```python\n", 490 | "# Seleccionamos una sola columna.\n", 491 | "serie_columna = df.loc[:, ['Columna1']]\n", 492 | " \n", 493 | "# Seleccionamos más de una columna.\n", 494 | "df_columnas = df.loc[:, ['Columna1','Columna2']]\n", 495 | " \n", 496 | "# Seleccionamos más de una fila.\n", 497 | "df_filas = df.loc[['Indice1', 'Indice2'], :]\n", 498 | "```\n", 499 | "Es importante notar que esta selección no afecta al DataFrame original, y que además lo que no se selecciona se conserva (por ejemplo, al seleccionar una sola columna, el nuevo DataFrame conserva todas las filas). Veamos un ejemplo con los datos de densidad poblacional.\n" 500 | ] 501 | }, 502 | { 503 | "cell_type": "code", 504 | "metadata": { 505 | "id": "Z-9dVIP5xHCy" 506 | }, 507 | "source": [ 508 | "# Seleccionamos dos columnas\n", 509 | "rank_densidad = df_poblacion.loc[:,['Rank', 'Density(pop/km2)']]\n", 510 | "rank_densidad.head()" 511 | ], 512 | "execution_count": null, 513 | "outputs": [] 514 | }, 515 | { 516 | "cell_type": "code", 517 | "metadata": { 518 | "id": "xGDmr62wxQVO" 519 | }, 520 | "source": [ 521 | "# Seleccionamos una sola columna\n", 522 | "poblacion = df_poblacion.loc[:,['Population']]\n", 523 | "poblacion " 524 | ], 525 | "execution_count": null, 526 | "outputs": [] 527 | }, 528 | { 529 | "cell_type": "code", 530 | "metadata": { 531 | "id": "kOzDXJkVzo0y" 532 | }, 533 | "source": [ 534 | "# Seleccionamos solo 3 países (3 filas)\n", 535 | "paises_seleccionados = df_poblacion.loc[['India', 'Taiwan', 'Haiti'],:]\n", 536 | "paises_seleccionados" 537 | ], 538 | "execution_count": null, 539 | "outputs": [] 540 | }, 541 | { 542 | "cell_type": "markdown", 543 | "metadata": { 544 | "id": "GghoO0aHWhqZ" 545 | }, 546 | "source": [ 547 | "También puedes seleccionar al mismo tiempo columnas y filas:\n", 548 | "\n", 549 | "
\n", 550 | " \n", 551 | "
\n", 552 | "\n", 553 | "Ejercicio: \n", 554 | "- Del DataFrame de densidad poblacional, filtra las columnas de población y área, y las filas de Singapore, Bangladesh y Lebanon. " 555 | ] 556 | }, 557 | { 558 | "cell_type": "code", 559 | "metadata": { 560 | "id": "Lwwj6bzxe2GS" 561 | }, 562 | "source": [ 563 | "# To-Do\n" 564 | ], 565 | "execution_count": null, 566 | "outputs": [] 567 | }, 568 | { 569 | "cell_type": "markdown", 570 | "metadata": { 571 | "id": "tuD5iy6gfp9k" 572 | }, 573 | "source": [ 574 | "Finalmente, puedes obtener una única celda de dos maneras:\n", 575 | "\n", 576 | "```python\n", 577 | "dato = df.loc['Fila', 'Columna']\n", 578 | "dato = df.at['Fila', 'Columna'] # Lo mismo, pero más rápido\n", 579 | "```\n", 580 | "Por ejemplo, obtenemos la densidad poblacional de la India:\n" 581 | ] 582 | }, 583 | { 584 | "cell_type": "code", 585 | "metadata": { 586 | "id": "6f91qlAxgarO" 587 | }, 588 | "source": [ 589 | "densidad_india = df_poblacion.at['India', 'Density(pop/km2)']\n", 590 | "print(densidad_india)" 591 | ], 592 | "execution_count": null, 593 | "outputs": [] 594 | }, 595 | { 596 | "cell_type": "markdown", 597 | "metadata": { 598 | "id": "uhYn4toLNot3" 599 | }, 600 | "source": [ 601 | "## Selección de datos por posición.\n", 602 | " \n", 603 | "En la sección anterior, seleccionamos dado a **etiquetas**, esto es, con los nombres de las filas y las columnas. Podemos hacer lo mismo pero está vez con la **posición**. Para esto, en lugar de **loc()** y **at()**, usamos **iloc()** y **iat()**. \n", 604 | " \n", 605 | "```python\n", 606 | "# Seleccionamos las primeras 2 columnas.\n", 607 | "df_columnas = df.iloc[:, 0:1]\n", 608 | " \n", 609 | "# Seleccionamos las últimas 3 filas\n", 610 | "df_filas = df.iloc[-3:, :]\n", 611 | " \n", 612 | "# Elemento unico\n", 613 | "dato = df.iat[0, 0]\n", 614 | "```\n", 615 | "Retomamos el ejemplo con la densidad de población.\n" 616 | ] 617 | }, 618 | { 619 | "cell_type": "code", 620 | "metadata": { 621 | "id": "AHk_654sNozk" 622 | }, 623 | "source": [ 624 | "poblacion_area = df_poblacion.iloc[:, 1:3]\n", 625 | "poblacion_area.head(3)" 626 | ], 627 | "execution_count": null, 628 | "outputs": [] 629 | }, 630 | { 631 | "cell_type": "code", 632 | "metadata": { 633 | "id": "eSpR6VgmkAds" 634 | }, 635 | "source": [ 636 | "tres_paises = df_poblacion.iloc[-3:, :]\n", 637 | "tres_paises" 638 | ], 639 | "execution_count": null, 640 | "outputs": [] 641 | }, 642 | { 643 | "cell_type": "code", 644 | "metadata": { 645 | "id": "v5KjssyWkoAb" 646 | }, 647 | "source": [ 648 | "dato = df_poblacion.iat[3, 3]\n", 649 | "print(dato)" 650 | ], 651 | "execution_count": null, 652 | "outputs": [] 653 | }, 654 | { 655 | "cell_type": "markdown", 656 | "metadata": { 657 | "id": "MeiC0lYQlUJF" 658 | }, 659 | "source": [ 660 | "Ejercicio: \n", 661 | "- Del DataFrame del Titanic, filtra y quédate solo con columnas y filas pares." 662 | ] 663 | }, 664 | { 665 | "cell_type": "code", 666 | "metadata": { 667 | "id": "Mb7xZTJSlUy6" 668 | }, 669 | "source": [ 670 | "# To Do" 671 | ], 672 | "execution_count": null, 673 | "outputs": [] 674 | }, 675 | { 676 | "cell_type": "markdown", 677 | "metadata": { 678 | "id": "R7wnDW31No5V" 679 | }, 680 | "source": [ 681 | "## Operaciones básicas: Estadísticos.\n", 682 | " \n", 683 | "Como se ha mencionado anteriormente, en cada columna normalmente se tendrá una **variable**, como nombres, edad, etc. y en cada fila habrá un registro de esa variable. Hay diversos **estadísticos** que podemos calcular para conocer más sobre la variable y como se comporta. Por ejemplo, si suponemos que una variable sigue un comportamiento normal, entonces conocer su media (promedio) $\\mu$ y su desviación estándar $\\sigma$ nos será de mucha utilidad. Si $\\mu = 10$ y $\\sigma = 3$, tenemos:\n", 684 | " \n", 685 | "
\n", 686 | " \n", 687 | "
\n", 688 | " \n", 689 | "Si quieres ver como hacer una gráfica como esta con Python, visita este [link](https://gist.github.com/GabrielMissael/6987ffd5e7fd83e2906ae201245d847b#file-normal_dist-py). Ya obtuvimos algunos valores con **.describe()**, y ahora veremos algunas otras funciones útiles.\n", 690 | " \n", 691 | "```python\n", 692 | "# Obtenemos la media de todas las columnas\n", 693 | "promedios = df.mean()\n", 694 | " \n", 695 | "# Media de una sola columna usando .loc()\n", 696 | "promedio = df.loc[:,'Columna1'].mean()\n", 697 | " \n", 698 | "# Podemos usar describe() en solo una sección del df\n", 699 | "descripcion = df.iloc[0:15, [2, 4]]\n", 700 | " \n", 701 | "# También podemos obtener la desviación estándar\n", 702 | "stds = df.std()\n", 703 | " \n", 704 | "# Valores mínimos y máximos\n", 705 | "maxs = df.max()\n", 706 | "mins = df.min()\n", 707 | "```\n", 708 | "Obtengamos algunos valores del dataframe de las casas de California:\n" 709 | ] 710 | }, 711 | { 712 | "cell_type": "code", 713 | "metadata": { 714 | "id": "gdqnp3gxn26h" 715 | }, 716 | "source": [ 717 | "# Promedio de población en cada sección\n", 718 | "promedio_poblacion = df_casas.loc[:,'population'].mean()\n", 719 | "promedio_poblacion" 720 | ], 721 | "execution_count": null, 722 | "outputs": [] 723 | }, 724 | { 725 | "cell_type": "code", 726 | "metadata": { 727 | "id": "1wwIh691oAmf" 728 | }, 729 | "source": [ 730 | "# Desviaciones estándar de cada variable\n", 731 | "stds = df_casas.std()\n", 732 | "stds" 733 | ], 734 | "execution_count": null, 735 | "outputs": [] 736 | }, 737 | { 738 | "cell_type": "code", 739 | "metadata": { 740 | "id": "hvCQIiLzoc9Z" 741 | }, 742 | "source": [ 743 | "# Obtenemos el intervalo de las variables\n", 744 | "mins = df_casas.min()\n", 745 | "maxs = df_casas.max()\n", 746 | "intervalo = maxs-mins\n", 747 | "intervalo" 748 | ], 749 | "execution_count": null, 750 | "outputs": [] 751 | }, 752 | { 753 | "cell_type": "markdown", 754 | "metadata": { 755 | "id": "xT9hcuKJNpEq" 756 | }, 757 | "source": [ 758 | "## Operaciones básicas: Apply.\n", 759 | " \n", 760 | "En muchas ocasiones, no sólo estaremos interesados en consultar o describir los datos, si no también en **operarlos**. Podemos aplicar funciones a los datos para obtener valores de interés. Para esto, usamos **.apply()**.\n", 761 | " \n", 762 | "```python\n", 763 | "# Aplicamos la función seno a los datos\n", 764 | "df_seno = df.apply(np.sin)\n", 765 | "```\n", 766 | "Veamos un ejemplo:\n" 767 | ] 768 | }, 769 | { 770 | "cell_type": "code", 771 | "metadata": { 772 | "id": "8csO2fqGNpKT" 773 | }, 774 | "source": [ 775 | "df_seno = df_poblacion.apply(np.sin)\n", 776 | "df_seno.head()" 777 | ], 778 | "execution_count": null, 779 | "outputs": [] 780 | }, 781 | { 782 | "cell_type": "markdown", 783 | "metadata": { 784 | "id": "Whmh__Y7pgPq" 785 | }, 786 | "source": [ 787 | "En este caso no tiene mucho sentido aplicar $sin(x)$ a datos de población y área; \n", 788 | " \n", 789 | "**Ejercicio**\n", 790 | "Queremos conocer la densidad de los países el siguiente año. Si suponemos que la población de todos crecerá un $5\\%$, entonces:\n", 791 | "- Calcula la nueva población y actualiza esta columna." 792 | ] 793 | }, 794 | { 795 | "cell_type": "code", 796 | "metadata": { 797 | "id": "WU4HNrheqRKL" 798 | }, 799 | "source": [ 800 | "# TO DO\n" 801 | ], 802 | "execution_count": null, 803 | "outputs": [] 804 | }, 805 | { 806 | "cell_type": "markdown", 807 | "metadata": { 808 | "id": "AiPyGKEuNpO2" 809 | }, 810 | "source": [ 811 | "## Unión de datos: Concatenación\n", 812 | " \n", 813 | "Podemos unir dos DataFrames. Si ambos comparten columnas, entonces será como agregar más filas al final: \n", 814 | " \n", 815 | "
\n", 816 | " \n", 817 | "
\n", 818 | " \n", 819 | "Si se tienen algunas columnas diferentes, el DataFrame final tendrá columnas extra y **valores faltantes** (aunque también puedes elegir eliminar las columnas que no coinciden).\n", 820 | " \n", 821 | "Para esto, usamos: \n", 822 | " \n", 823 | "```python\n", 824 | "# Unimos dos DataFrames.\n", 825 | "df_nuevo = pd.concat([df1, df2])\n", 826 | "```\n", 827 | "Veamos algunos ejemplos:\n" 828 | ] 829 | }, 830 | { 831 | "cell_type": "code", 832 | "metadata": { 833 | "id": "CrvItaXLNpTV" 834 | }, 835 | "source": [ 836 | "df1 = pd.DataFrame(data = np.random.rand(3, 3), \n", 837 | " columns = ['A', 'B', 'C'])\n", 838 | "df1" 839 | ], 840 | "execution_count": null, 841 | "outputs": [] 842 | }, 843 | { 844 | "cell_type": "code", 845 | "metadata": { 846 | "id": "9mnXjswntWSj" 847 | }, 848 | "source": [ 849 | "df2 = pd.DataFrame(data = np.random.rand(2, 3), \n", 850 | " columns = ['A', 'B', 'C'], \n", 851 | " index = ['Elemento 1', 'Elemento 2'])\n", 852 | "df2" 853 | ], 854 | "execution_count": null, 855 | "outputs": [] 856 | }, 857 | { 858 | "cell_type": "code", 859 | "metadata": { 860 | "id": "963a_Iufta1Z" 861 | }, 862 | "source": [ 863 | "df3 = pd.DataFrame(data = np.random.rand(2, 3), columns = ['A', 'B', 'D'])\n", 864 | "df3" 865 | ], 866 | "execution_count": null, 867 | "outputs": [] 868 | }, 869 | { 870 | "cell_type": "code", 871 | "metadata": { 872 | "id": "fNSbIP_6t5w4" 873 | }, 874 | "source": [ 875 | "df = pd.concat([df1, df2])\n", 876 | "df" 877 | ], 878 | "execution_count": null, 879 | "outputs": [] 880 | }, 881 | { 882 | "cell_type": "code", 883 | "metadata": { 884 | "id": "iTBCR7IGuCE0" 885 | }, 886 | "source": [ 887 | "# Outer o inner\n", 888 | "df = pd.concat([df1, df3], join = 'outer')\n", 889 | "df" 890 | ], 891 | "execution_count": null, 892 | "outputs": [] 893 | }, 894 | { 895 | "cell_type": "markdown", 896 | "metadata": { 897 | "id": "NbRrO25Tx7MF" 898 | }, 899 | "source": [ 900 | "Ejercicio: \n", 901 | "- A partir del dataframe que creaste con la nueva población, crea uno nuevo pero con la densidad poblacional correcta." 902 | ] 903 | }, 904 | { 905 | "cell_type": "code", 906 | "metadata": { 907 | "id": "GGZHlRnhOfCg" 908 | }, 909 | "source": [ 910 | "# To-Do\n" 911 | ], 912 | "execution_count": null, 913 | "outputs": [] 914 | }, 915 | { 916 | "cell_type": "markdown", 917 | "metadata": { 918 | "id": "LNrJfQTXyJsD" 919 | }, 920 | "source": [ 921 | "## Bonus: Gráficas en pandas.\n", 922 | "\n", 923 | "Podemos gráficar fácilmente los datos en un DataFrame:\n", 924 | "\n", 925 | "```python\n", 926 | "# Gráfica de linea\n", 927 | "df.plot(x = 'Columna1', y = 'Columna2')\n", 928 | "\n", 929 | "# Gráfica de puntos\n", 930 | "df.plot.scatter(x = 'Columna1', y = 'Columna2')\n", 931 | "```\n", 932 | "\n" 933 | ] 934 | }, 935 | { 936 | "cell_type": "code", 937 | "metadata": { 938 | "id": "TkjKQeXdyi5g" 939 | }, 940 | "source": [ 941 | "df_poblacion.plot(x = 'Rank', y = 'Density(pop/km2)')" 942 | ], 943 | "execution_count": null, 944 | "outputs": [] 945 | }, 946 | { 947 | "cell_type": "code", 948 | "metadata": { 949 | "id": "jQQNMEFHyiwz" 950 | }, 951 | "source": [ 952 | "df_casas.plot.scatter(x = 'population', y = 'total_rooms', alpha = 0.5)" 953 | ], 954 | "execution_count": null, 955 | "outputs": [] 956 | }, 957 | { 958 | "cell_type": "markdown", 959 | "metadata": { 960 | "id": "7Sv-GME3nPON" 961 | }, 962 | "source": [ 963 | "-----\n", 964 | "> Contenido creado por **Missael Barco** ([CdeCMx](https://clubesdeciencia.mx/) / [Future Lab](https://futurelab.mx/), 2021)
\n", 965 | "> Contacto: [@GMissaelBarco](https://twitter.com/GMissaelBarco), missaelgabo@gmail.com\n" 966 | ] 967 | } 968 | ] 969 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Curso de introducción a la programación científica con Python 2 | 3 | ¡Aprende a programar en lenguaje Python con Clubes de Ciencia México y Future Lab! 🐍🚀 4 | 5 | Este es un curso diseñado y preparado con mucho 💙 y 💻 para las y los Cluberos que están por comenzar la travesía de iniciar en el mundo de la programación. Accede a los contenidos del curso en nuestro sitio oficial: [https://futurelab.mx/cdecmx](https://futurelab.mx/cdecmx) 6 | 7 | ### Requisitos 8 | 9 | Conoce todos los detalles en el [sitio oficial del curso](https://futurelab.mx/cdecmx). 10 | 11 | ### Temario 12 | 13 | Conoce el temario completo que ha sido dispuesto a través de los 4 módulos a continuación: 14 | 15 |
16 | A. Introducción a Python y la programación 17 | 18 | - ¿Qué es programar? 19 | - ¿Qué es y por qué Python? 20 | - Introducción al entorno de trabajo → Google Colab + Markdown 21 | - I/O - ¡Hola mundo! 22 | - Variables, tipos y conversión 23 | - Operaciones básicas 24 | - Condicionales 25 | - Listas y tuplas 26 | - Ciclos 27 | - Diccionarios 28 | - Funciones 29 | - Módulos y paquetes 30 |
31 | 32 |
33 | B. ¿Cómputo numérico? Conoce NumPy 34 | 35 | - Introducción a [NumPy](https://www.nature.com/articles/s41586-020-2649-2) 36 | - Atributos, tamaño y forma 37 | - Indexación y slicing 38 | - Operaciones básicas, broadcasting 39 | - Valores únicos y cuentas 40 | - Matrices en NumPy 41 | - Trasposición, aplanamiento y reversa 42 | - Módulo random 43 | - Módulo de álgebra lineal 44 | - Conoce SciPy 45 |
46 | 47 |
48 | C. ¿Cómo puedo importar y trabajar con datos? Conoce Pandas 49 | 50 | - Introducción a Pandas 51 | - Dónde encontrar datos 52 | - Carga de datos de diferentes formatos 53 | - Series y DataFrames 54 | - Revisando los datos 55 | - Selección de datos por columna 56 | - Selección de datos por posición 57 | - Operaciones básicas: Estadísticos 58 | - Operaciones básicas: Apply 59 | - Unión de datos: Concatenación 60 | - Agrupación - groupby 61 |
62 | 63 |
64 | D. ¡Ciencia reproducible, datos, GitHub y más! 65 | 66 | - Ambientes de computación: 67 | - Instalación de Python y Anaconda 68 | - El ecosistema de Jupyter 69 | - Dónde encontrar datos 70 | - Ciencia reproducible → Semillas aleatorias 71 | - Visualización 72 | - Filosofía 73 | - Diagramas básicos 74 | - GitHub y repositorios 75 | - Creación de repositorios 76 | - GitHub Pages 77 | - GitHub Student Developer Pack 78 |
79 | 80 | 81 | ### FAQ 82 | 83 |
84 | ¿El curso tiene algún costo? 85 | No 86 |
87 | 88 | 89 | ### Roadmap 90 | 91 | #### CONSIDERACIONES: 92 | - Tiempo: 4-6 hrs 93 | - Considerar casos de aplicación por tema 94 | - Considerar entregables por tema 95 | - ~~Testers del curso~~ 96 | - El ecosistema Python.... Tipo si tengo X problema, ¿cómo encuentro la librería que lo resuelve? 97 | - Agregar objetivos o metas por sección 98 | - Evaluación previa y posterior al curso → Muy importante: Documentar 99 | --------------------------------------------------------------------------------