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/activateEsto 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_wsAhora puedes ejecutar Jupyter usando el comando:
$ jupyter notebookEsto 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=0Toma 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://
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 picatrixPero empecemos importando las dos bibliotecas que usaremos a lo largo del tutorial, pandas y numpy.
import numpy as np
import pandas as pdVerá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 ~/ && pwdEsto 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:
%magicUn 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 * 10Este 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 = %pwdoutputPicatrix¶
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:
%picatrixmagicsCada 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 --helpo
nombre_magic_func?Veamos un ejemplo:
%picatrixmagics --helpNumpy 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 * 10Los arreglos numpy también pueden ser multidimensionales:
arr = np.random.randn(4, 4)arrEsto también puede multiplicarse, por ejemplo:
arr * 3arr + arrTambié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'])arrPara 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'])serAhora puedes acceder a cada objeto usando la notación de punto o corchetes
ser.fooser['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'
})serser.notesHay 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)dfPodemos empezar mirando la forma del dataframe:
df.shapeEsto 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'] = 5452Esto se aplicará a todo el dataframe:
dfTambién puedes crear valores que contengan partes de otras columnas
df['message'] = df['Notes'] + ' --> ' + df['Important'].astype(str) + ' [' + df['Value'].astype(str) + ']'dfTambién podemos extraer valores de una cadena y asignarlos a otra.
df['stuff'] = df['Notes'].str.extract(r'\b([sS][^ $]+)')dfConteo 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:
Fila única
Lista de filas
Rebanada
Máscara booleana
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)dfAhora 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')dfSi 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