Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Introducción Rápida

Open In Colab

Introducción Rápida

Este notebook es una introducción rápida sobre qué son los notebooks de Colab/Jupyter.

Gran parte del trabajo en un notebook consiste en trabajar con una estructura de datos de Python llamada pandas. Este notebook proporciona ejemplos cortos para una introducción simple a esta estructura de datos.

Un buen primer paso es ver este video introductorio de 10 minutos

Para lectura adicional consulta entre otros:

Introducción

Vamos a usar Python como lenguaje de programación. Qué es Python, cómo funciona, etc., está fuera del alcance de este tutorial. Hay muchos tutoriales mejores en línea que explican eso.

Python es un lenguaje interpretado, donde el intérprete ejecuta una instrucción a la vez. Para ciencia de datos, usamos IPython, que es un intérprete mejorado de Python. Puedes ejecutar este intérprete de varias maneras, incluyendo Jupyter o Colab. Jupyter y Colab tienen una interfaz web para ejecutar código Python en un notebook. Un notebook es un tipo de documento interactivo para código. Es una mezcla de celdas de texto y celdas de código, donde el texto puede formatearse en markdown y el código depende del intérprete adjunto (aquí usaremos Python).

Jupyter

Una de las formas más fáciles de ejecutar e instalar Jupyter es usar un entorno virtual en Python, que crea un entorno Python separado donde puedes instalar bibliotecas.

En un sistema Debian Linux puedes ejecutar:

$ sudo apt-get install python3-venv
$ python3 -m venv jupyter_env
$ source jupyter_env/bin/activate

Esto configurará el entorno, luego hay que instalar dependencias. Estas dependerán de para qué lo vayas a usar. Para una configuración básica puedes instalar:

$ pip install jupyter altair vega-datasets vega pandas jupyter_http_over_ws wheel
$ jupyter serverextension enable --py jupyter_http_over_ws

Ahora puedes ejecutar Jupyter usando el comando:

$ jupyter notebook

Esto debería abrir automáticamente una página web en tu navegador con la interfaz de Jupyter. Si no, puedes navegar a http://localhost:8888

Para ejecutar este notebook en Jupyter simplemente elige “Archivo | Descargar .ipynb”, guarda el archivo en el mismo directorio donde iniciaste Jupyter y deberías verlo en la lista (puede que necesites refrescar la ventana del navegador de Jupyter)

Colab

Para Colab simplemente visita el notebook en el sitio de Colab y haz clic en conectar. La advertencia aquí es que requiere tener una cuenta activa de Google. Solo tienes que hacer clic en el botón en la esquina superior derecha que dice “Conectar” y puedes empezar a ejecutar el código aquí.

También puedes tener un entorno mixto donde tienes tu propio kernel de Jupyter ejecutándose pero usando Colab como frontend, para eso puedes seguir las instrucciones aquí o iniciar el notebook de Jupyter usando este comando:

$ jupyter notebook \
  --NotebookApp.allow_origin='https://colab.research.google.com' \
  --port=8888 \
  --NotebookApp.port_retries=0

Toma nota de la URL de autenticación que aparece al ejecutar el notebook, debería verse algo así:

[I 14:39:29.255 NotebookApp] Serving notebooks from local directory: <RUTA>
[I 14:39:29.255 NotebookApp] Jupyter Notebook <VERSION> is running at:
[I 14:39:29.255 NotebookApp] http://localhost:8888/?token=<TOKEN>
...

Copia la URL que se ve así: “http://localhost:8888/?token=”. Luego haz clic en el enlace de Colab, en la esquina superior derecha haz clic en el pequeño triángulo y selecciona “Conectar a un entorno de ejecución local”

Inicio

Lo primero que queremos hacer es instalar la biblioteca picatrix (si estamos ejecutando esto en una instancia en la nube, puedes omitir si ya está instalada)

!pip install picatrix

Pero empecemos importando las dos bibliotecas que usaremos a lo largo del tutorial, pandas y numpy.

import numpy as np
import pandas as pd

Verás esta tradición de importar numpy como np y pandas como pd en toda la literatura, por lo tanto mantendremos eso aquí también.

Una forma simple de ver pandas es como una tabla de base de datos, donde tienes columnas y filas y luego algunas operaciones que puedes hacer sobre estas tablas/filas.

Una cosa a tener en cuenta con un notebook IPython como este es el autocompletado con tab. En las celdas de código puedes presionar la tecla tab y se buscará en el espacio de nombres, pruébalo aquí con la biblioteca pandas:

pd.

Otra cosa útil que puede que quieras conocer es que también puedes ejecutar todos los comandos regulares de shell desde un notebook. Si una celda de código comienza con ! se ejecutará en el shell, por ejemplo:

!ls ~/ && pwd

Esto puede ser útil, especialmente si estás ejecutando un kernel local, ya sea desde un notebook de Jupyter o uno de Colab conectado a un kernel local.

Otra opción que puede ser útil es usar ? después de una función para obtener el docstring de la función (o ?? para obtener el código):

pd.read_csv?

Esto se conoce como introspección de objetos.

También puedes usar esto para encontrar funciones cuando mezclas el uso con el carácter comodín *, como:

pd.read_*?

Esto producirá una lista de todas las funciones .read_ dentro de la biblioteca pandas.

Magics

Otra característica de IPython son los magics. Estos son comandos especiales de IPython que no están integrados en Python mismo. Hay magics incorporados así como definidos por el usuario.

Los magics se identifican anteponiendo el nombre del magic con % o %%. Un ejemplo sería %run o %paste que se encargan de ejecutar un archivo Python dentro de una celda, o pegar código desde tu portapapeles.

Los magics son ya sea magics de línea (%) donde los parámetros están todos en una sola línea, o magics de celda (%%) donde los parámetros pueden definirse usando múltiples líneas.

Ve más información aquí o ejecuta este comando:

%magic

Un magic incorporado útil es %timeit para medir tiempos de ejecución de celdas de código, por ejemplo:

%%timeit
for index in range(0, 10):
  _ = index * 10

Este es un código sin sentido, pero se usa para demostrar cómo puedes medir el tiempo de ejecución de un fragmento de código usando el magic %%timeit. En este caso es un magic de celda, así que todo el código en la celda es evaluado.

También puedes asignar la salida de algunos magics a variables usando esto:

output = %pwd
output

Picatrix

La biblioteca o paquete picatrix está orientado a proporcionar a los analistas un conjunto de magics y funciones Python exportadas orientadas al análisis de seguridad.

Para usar la biblioteca picatrix necesitamos importarla e inicializarla, hagámoslo:

from picatrix import notebook_init

notebook_init.init()

Para obtener una lista de todos los magics que son parte de la biblioteca picatrix, usa el magic %picatrixmagics:

%picatrixmagics

Cada magic se registra en el espacio de nombres de tres maneras:

  • ‘%nombre_magic’ - magic de línea

  • ‘%%nombre_magic’ - magic de celda

  • 'nombre_magic_func()` - una función regular de Python.

Para obtener más ayuda sobre cada magic, puedes ejecutar:

%nombre_magic --help

o

nombre_magic_func?

Veamos un ejemplo:

%picatrixmagics --help

Numpy y Pandas

Hablemos nuevamente sobre numpy y pandas. numpy o Numerical Python es una de las bibliotecas fundamentales más importantes para computación numérica en Python. Esta guía no entrará en detalles sobre el funcionamiento interno de numpy, hay muchas guías en línea que proporcionan eso si estás interesado.

La parte importante aquí es que numpy proporciona una API C rápida para trabajar con arreglos multidimensionales. Y contiene funciones matemáticas para operar sobre arreglos completos de datos sin requerir el uso de bucles.

Arreglos Numpy

Empecemos a explorar un arreglo numpy simple.

arr = np.arange(10000)

Veamos las primeras 10 entradas del arreglo:

arr[:10]

Y la longitud

print(len(arr))

Exploremos la diferencia en tiempo entre una lista y un arreglo numpy

arr_list = list(range(10000))
print(len(arr_list))

Veamos el tiempo al multiplicar un arreglo vs una lista por un número:

%time a = [x * 10 for x in arr_list]
%time a = arr * 10

Los arreglos numpy también pueden ser multidimensionales:

arr = np.random.randn(4, 4)
arr

Esto también puede multiplicarse, por ejemplo:

arr * 3
arr + arr

También puedes seleccionar una entrada individual del arreglo, por ejemplo si queremos el elemento en la primera fila, tercera columna (recuerda que el conteo comienza desde cero):

arr[0, 2]

O podemos elegir un subconjunto, usando rebanado (slicing).

Elijamos las primeras dos filas:

arr[0:2]

o los elementos del medio de las primeras dos filas:

arr[0:2, 1:3]

También puedes indexar basándote en cadenas si el arreglo es un arreglo de cadenas, por ejemplo:

arr = np.array(['time', 'picatrix', 'sketch', 'magic', 'wizard'])
arr

Para obtener un arreglo booleano que puede usarse para filtrar, construimos una consulta booleana:

arr == 'time'
arr[arr == 'time']

Hay muchas más propiedades importantes de los arreglos numpy que no tendremos tiempo de cubrir en esta introducción muy breve.

Series de Pandas

Pasemos a hablar sobre pandas de Python. La mayor diferencia entre pandas y numpy es que pandas está diseñado para trabajar con datos tabulares, piensa más en una hoja de cálculo o una base de datos.

Pandas define dos estructuras de datos principales, Series y DataFrame. Una Series es un objeto similar a un arreglo unidimensional que contiene una secuencia de valores. Un ejemplo puede ser:

pd.Series(['a', 'b', 'c', 'd', 'e'])

Las Series también pueden tener índices o etiquetas adjuntas a cada valor (donde entonces son casi similares a un dict)

ser = pd.Series(['a', 'b', 'c', 'd', 'e'], index=['foo', 'bar', 'more', 'note', 'extra'])
ser

Ahora puedes acceder a cada objeto usando la notación de punto o corchetes

ser.foo
ser['foo']

También podemos convertir un objeto Series en un dict, o crear un objeto Series desde un dict:

ser.to_dict()
ser = pd.Series({
    'stuff': 134,
    'more': 11,
    'notes': 'extra stuff'
})
ser
ser.notes

Hay muchas funciones incorporadas para trabajar con Series que no tendremos tiempo de cubrir en este tutorial. Pero para el propósito de analizar datos de texto, presta especial atención a str.contains y str.extract, por ejemplo:

ser.str.contains('stuff')
ser.str.extract(r' (s[^ $]+)')

DataFrame de Pandas

Un DataFrame, que es el objeto con el que más trabajarás, es una tabla rectangular de datos y contiene una colección ordenada de columnas. Puedes pensar en él como un dict de Series, todas compartiendo el mismo índice.

lines = [
    {'Important': True, 'Value': 1345, 'Notes': 'Stuff IS Stuff'},
    {'Important': True, 'Value': 23, 'Notes': 'This does not contain any word...'},
    {'Important': True, 'Value': 523, 'Notes': 'We have a lot of text in here, including stuff'},
    {'Important': False, 'Value': 100, 'Notes': 'Here is a word that sounds like stuff but is in fact soooo much longer'},
]

df = pd.DataFrame(lines)
df

Podemos empezar mirando la forma del dataframe:

df.shape

Esto nos dice que contiene cuatro filas y cada fila tiene tres columnas. Veamos las primeras dos filas:

df.head(2)

O las últimas 2:

df.tail(2)

También podemos ver solo el valor de una sola columna:

df['Value']

Lo que nos devolverá un objeto Series, sobre el que podemos usar todas las operaciones de Series.

df['Notes'].str.contains('stuff')

Luego también podemos usar este filtrado para filtrar las filas en el dataframe. Así que para obtener solo las filas que contienen la palabra stuff podemos hacer:

df[df['Notes'].str.contains('stuff')]

También podemos filtrar todos los valores no importantes:

df[df['Important']]

También podemos asignar valores aquí:

df['NewValue'] = 5452

Esto se aplicará a todo el dataframe:

df

También puedes crear valores que contengan partes de otras columnas

df['message'] = df['Notes'] + ' --> ' + df['Important'].astype(str) + ' [' + df['Value'].astype(str) + ']'
df

También podemos extraer valores de una cadena y asignarlos a otra.

df['stuff'] = df['Notes'].str.extract(r'\b([sS][^ $]+)')
df

Conteo y Valores Únicos

Otra propiedad muy útil es la capacidad de resumir los datos:

df['Important'].value_counts()

O encontrar todos los valores únicos de una columna:

df['Important'].unique()

También hay dos funciones incorporadas que proporcionan una visión general de los datos:

df.info()
df.describe()

Rebanar un DataFrame

Un dataframe puede rebanarse usando filtros booleanos, por ejemplo:

df[df['Important']]

Estos pueden combinarse para dar resultados más granulares:

df[(df['Important']) & (df['Notes'].str.contains('stuff', case=False))]

Las rebanadas pueden guardarse para filtrar más:

df_slice = df[(df['Important']) & (df['Notes'].str.contains('stuff', case=False))]

df_slice[df_slice.Value > 1000]

Selección Directa

Hay 2 formas principales de recuperar subconjuntos de un dataframe:

  • .iloc[]

  • .loc[]

.loc está basado en etiquetas. .iloc está basado en posición.

Ambos pueden usarse de 5 maneras diferentes:

  1. Fila única

  2. Lista de filas

  3. Rebanada

  4. Máscara booleana

  5. Una función (que recibe el dataframe como entrada), que devuelve cualquiera de los 4 anteriores

Para obtener la primera fila del dataframe usa iloc

df.iloc[0]

O las primeras dos filas:

df.iloc[0:2]

iloc usa la posición entera dentro del dataframe mientras que loc usa etiquetas como se indicó anteriormente. En este caso la etiqueta también es un entero.

df.loc[2]

También podemos elegir una columna

df.loc[2:3, 'Value']

También podemos cambiar las etiquetas aquí:

df['NewIndex'] = pd.Series(['A', 'B', 'C', 'D'])
df.set_index('NewIndex', inplace=True)
df

Ahora podemos usar el nuevo índice

df.loc['B']

O obtener una rebanada:

df.loc['B':'D']

Ordenamiento

También podemos ordenar el dataframe:

df.sort_values('Value')

O en orden descendente:

df.sort_values('Value', ascending=False)

Rangos

Ranking reemplaza cada valor válido en un dataframe con su ordinal si el dataframe estuviera ordenado por esa columna (los empates reciben la media de los rangos).

df.rank()

O ranking por columnas

df.rank(axis='columns')

Si los valores son numéricos también puedes resumir los valores usando funciones como sum:

df.Value.sum()
df.Value.mean()
df.Value.cumsum()

Leyendo Datos

Una de las partes más importantes de usar pandas es leer los datos. Si no tienes datos entonces es difícil trabajar con ellos.

Pandas proporciona un montón de métodos para obtener datos, desde conectarse a bases de datos SQL hasta hojas de cálculo y CSVs. Este tutorial solo cubrirá lo más básico.

pd.read_*?

Esto te dará una visión general de qué funciones están disponibles. Si quieres saber más sobre una función específica escribe pd.read_excel?

Veamos la función más básica, que es leer un archivo CSV. Como no tenemos un archivo, simplemente generaremos uno muy básico y luego lo leeremos.

import csv

with open('/tmp/foobar.csv', 'w') as fw:
  writer = csv.writer(fw)
  writer.writerow(['First', 'Second', 'Third'])
  writer.writerow([1, 2, 4])
  writer.writerow([5, 3, 2])
  writer.writerow([1, 3, 0])
df = pd.read_csv('/tmp/foobar.csv')
df

Si el archivo CSV es muy grande, los datos pueden leerse en fragmentos:

for chunk in pd.read_csv('/tmp/foobar.csv', chunksize=2):
  print(chunk.shape)

Hay muchos más matices en la importación de datos que no se cubrirán en este tutorial básico.

Rellenando Datos Faltantes

TODO: Completar esto

Manipulando los Datos

TODO: Completar esto, agregar cómo cambiar valores, usar .apply y otras funciones para cambiar valores o agregar nuevas columnas