Vamos a ver las principales librerías para visualización de datos con Python y todos los tipos de gráficos que se pueden hacer con ellas. También veremos qué librería es recomendable usar en cada ocasión y las capacidades únicas de cada librería.
Empezaremos con la visualización más básica que es mirar los datos directamente, pasaremos después a hacer gráficos y finalmente haremos gráficos interactivos.
Datasets
Trabajaremos con dos datasets que se adaptaran a las visualizaciones que enseñamos en el artículo, los datasets los puedes descargar aquí.
Son datos de popularidad de búsquedas en internet de tres términos relacionados con inteligencia artificial (data science, machine learning y deep learning). Han sido extraídos de un famoso buscador.
Hay dos archivos temporal.csv y mapa.csv. El primero lo utilizaremos en la gran mayoría del tutorial, incluye datos de popularidad de los tres términos a lo largo del tiempo (de 2004 a la actualidad, 2020). Además he añadido una variable categórica (unos y ceros) para demostrar las funcionalidades de los gráficos con variables categóricas.
El archivo mapa.csv incluye datos de popularidad separados por países. Lo utilizaremos en la última sección del artículo cuando trabajemos con mapas.
Pandas
Antes de pasar a métodos más complejos, empecemos con la manera más básica de visualizar datos. Simplemente utilizaremos pandas para dar un vistazo a los datos y hacernos una idea de como están distribuidos.
Lo primero que debemos hacer es visualizar unos cuantos ejemplos para ver qué columnas hay, qué información contienen, cómo están codificados los valores…
import pandas as pd df = pd.read_csv('temporal.csv') df.head(10) #Visualizar las primeras 10 filas de datos
Con el comando describe vamos a ver cómo están distribuidos los datos, los máximos, los mínimos, la media, …
df.describe()
Con el comando info veremos qué tipo de datos incluye cada columna. Podríamos encontrarnos el caso de una columna que al visualizarla con el comando head parezca numérica pero si miramos datos posteriores haya valores en formato string, entonces la variable estará codificada como string.
df.info()
Por defecto, pandas nos limita el número de filas y columnas que nos muestra. Esto me molesta muchas veces porque quiero poder visualizar todos los datos.
Con estos comandos aumentamos los límites y podremos visualizar los datos enteros. Cuidado para esta opción con datasets grandes, podemos tener problemas para mostrarlos.
pd.set_option('display.max_rows', 500) pd.set_option('display.max_columns', 500) pd.set_option('display.width', 1000)
Usando los estilos de Pandas, podemos obtener mucha más información al visualizar la tabla. Primero definimos un diccionario de formato para que los números se muestren de una manera legible (con un cierto número de decimales, fecha y hora en un formato relevante, con un porcentaje, con una moneda, …). No te asustes, esto solo es una visualización y no cambia los datos, no tendrás ningún problema para procesarlos después.
Para poner un ejemplo de cada tipo, he añadido símbolos de moneda y porcentaje aunque no tengan ningún sentido para estos datos.
format_dict = {'data science':'${0:,.2f}', 'Mes':'{:%m-%Y}', 'machine learning':'{:.2%}'} #Nos aseguramos que la columna Mes tenga formato de fecha df['Mes'] = pd.to_datetime(df['Mes']) #Aplicamos el estilo en la visualización df.head().style.format(format_dict)
Podemos resaltar valores máximos y mínimos con colores.
format_dict = {'Mes':'{:%m-%Y}'} #Simplificamos el diccionario de formato con valores que sí que tienen sentido para nuestros datos df.head().style.format(format_dict).highlight_max(color='darkgreen').highlight_min(color='#ff0000')
Utilizamos un gradiente de color para visualizar los valores de los datos.
df.head(10).style.format(format_dict).background_gradient(subset=['data science', 'machine learning'], cmap='BuGn')
También podemos visualizar los valores de los datos mediante barras.
df.head().style.format(format_dict).bar(color='red', subset=['data science', 'deep learning'])
Además podemos combinar las funciones anteriores y generar una visualización más compleja.
df.head(10).style.format(format_dict).background_gradient(subset=['data science', 'machine learning'], cmap='BuGn').highlight_max(color='yellow')
Más información sobre estilizar visualizaciones con Pandas aquí: https://pandas.pydata.org/pandas-docs/stable/user_guide/style.html
Pandas Profiling
Pandas profiling es una librería que genera informes interactivos con nuestros datos, podemos ver la distribución de los datos, los tipos de los datos, posibles problemas que puedan tener. Es muy fácil de utilizar, con solo 3 líneas tenemos generado un informe que podemos enviar a quien queramos y que podrá utilizar aunque no sepa programación.
from pandas_profiling import ProfileReport prof = ProfileReport(df) prof.to_file(output_file='informe.html')
Puedes ver el informe interactivo generado a partir de los datos utilizados en el artículo, aquí
Puedes encontrar más información de Pandas Profiling en este artículo.
Matplotlib
Matplotlib es la librería más básica para visualizar datos gráficamente. Incluye muchos de los gráficos que se nos puedan ocurrir. Que sea básica no significa que no sea potente, muchas de las otras librerías de visualización de datos de las que vamos a hablar están basadas en ella.
Los gráficos de Matplotlib están formados por dos componentes principales, los ejes (las líneas que delimitan el área del gráfico) y la figura (donde dibujamos los ejes, títulos y cosas que se salgan del área de los ejes). Ahora vamos a crear el gráfico más simple posible:
import matplotlib.pyplot as plt plt.plot(df['Mes'], df['data science'], label='data science') #El parámetro label es para indicar la leyenda. Esto no quiere decir que se muestre, tendremos que usar otro comando que explicaré más adelante.
Podemos hacer las gráficas de múltiples variables en un mismo gráfico y así compararlas.
plt.plot(df['Mes'], df['data science'], label='data science') plt.plot(df['Mes'], df['machine learning'], label='machine learning') plt.plot(df['Mes'], df['deep learning'], label='deep learning')
No se ve muy claro a qué variable representa cada color. Vamos a mejorar el gráfico añadiendo leyenda y títulos.
plt.plot(df['Mes'], df['data science'], label='data science') plt.plot(df['Mes'], df['machine learning'], label='machine learning') plt.plot(df['Mes'], df['deep learning'], label='deep learning') plt.xlabel('Fecha') plt.ylabel('Popularidad') plt.title('Popularidad de términos relacionados con Inteligencia Artificial') plt.grid(True) plt.legend()
Si estás trabajando con Python desde la terminal o un script, después de definir el gráfico con las funciones que hemos escrito anteriormente utiliza plt.show(). Si estás trabajando desde jupyter notebook, añade %matplotlib inline al principio del archivo y ejecútalo antes de hacer el gráfico.
Podemos hacer múltiples gráficos en una misma figura. Esto va muy bien para comparar gráficas o para compartir datos de varios tipos de gráficos fácilmente con una sola imagen.
fig, axes = plt.subplots(2,2) axes[0, 0].hist(df['data science']) axes[0, 1].scatter(df['Mes'], df['data science']) axes[1, 0].plot(df['Mes'], df['machine learning']) axes[1, 1].plot(df['Mes'], df['deep learning'])
Podemos dibujar el gráfico con estilos diferentes para los puntos de cada variable:
plt.plot(df['Mes'], df['data science'], 'r-') plt.plot(df['Mes'], df['data science']*2, 'bs') plt.plot(df['Mes'], df['data science']*3, 'g^')
Ahora veamos unos cuantos ejemplos de los distintos gráficos que podemos hacer con Matplotlib. Empezamos con un scatterplot:
plt.scatter(df['data science'], df['machine learning'])
Ejemplo de un gráfico de barras:
plt.bar(df['Mes'], df['machine learning'], width=20)
Ejemplo de un histograma:
plt.hist(df['deep learning'], bins=15)
Podemos añadir un texto al gráfico, indicamos la posición del texto en las mismas unidades que vemos en el gráfico. En el texto podemos incluso añadir caracteres especiales siguiendo el lenguaje TeX
También podemos añadir marcadores que señalen a un punto concreto del gráfico.
plt.plot(df['Mes'], df['data science'], label='data science') plt.plot(df['Mes'], df['machine learning'], label='machine learning') plt.plot(df['Mes'], df['deep learning'], label='deep learning') plt.xlabel('Fecha') plt.ylabel('Popularidad') plt.title('Popularidad de términos relacionados con IA') plt.grid(True) plt.text(x='2010-01-01', y=80, s=r'$\lambda=1, r^2=0.8$') #Las coordenadas usan las mismas unidades que el gráfico plt.annotate('Aquí pasa algo!', xy=('2014-01-01', 30), xytext=('2006-01-01', 50), arrowprops={'facecolor':'red', 'shrink':0.05})
Galería de ejemplos:
En este enlace https://matplotlib.org/gallery/index.html podemos ver ejemplos de todos los tipos de gráficos que se pueden hacer con Matplotlib.
Seaborn
Seaborn es una librería basada en Matplotlib. Básicamente lo que nos aporta son gráficos más bonitos y funciones para realizar tipos de gráficos complejos con solo una línea de código.
Importamos la librería e inicializamos el estilo de los gráficos con sns.set(), sin este comando los gráficos seguirían teniendo el mismo estilo que Matplotlib. Mostramos uno de los gráficos más simples, un scatterplot
import seaborn as sns sns.set() sns.scatterplot(df['Mes'], df['data science'])
Podemos añadir información de más de dos variables en un mismo gráfico. Para ello utilizamos colores y tamaños. También hacemos un gráfico distinto según el valor de la columna categorical:
sns.relplot(x='Mes', y='deep learning', hue='data science', size='machine learning', col='categorical', data=df)
Uno de los gráficos más populares que aporta Seaborn es el heatmap. Es muy común usarlo para mostrar todas las correlaciones entre las variables de un dataset:
sns.heatmap(df.corr(), annot=True, fmt='.2f')
Otro de los más populares es el pairplot que nos muestra las relaciones entre todas las variables. Ojo con esta función si tenemos un dataset grande, como tiene que mostrar todos los puntos de datos tantas veces como columnas haya significa que al aumentar la dimensionalidad de los datos, aumenta exponencialmente el tiempo de procesado.
sns.pairplot(df)
Ahora hagamos el pairplot mostrando las gráficas segmentadas según los valores de la variable categorical
sns.pairplot(df, hue='categorical')
Un gráfico muy informativo es el jointplot que nos permite ver un scatterplot junto a un histograma de las dos variables y ver cómo están distribuidas:
sns.jointplot(x='data science', y='machine learning', data=df)
Otro gráfico interesante es el ViolinPlot:
sns.catplot(x='categorical', y='data science', kind='violin', data=df)
Podemos crear múltiples gráficos en una misma imagen igual que hacíamos con Matplotlib:
fig, axes = plt.subplots(1, 2, sharey=True, figsize=(8, 4)) sns.scatterplot(x="Mes", y="deep learning", hue="categorical", data=df, ax=axes[0]) axes[0].set_title('Deep Learning') sns.scatterplot(x="Mes", y="machine learning", hue="categorical", data=df, ax=axes[1]) axes[1].set_title('Machine Learning')
Galería de ejemplos:
En este enlace podemos ver ejemplos de todo lo que se puede hacer con Seaborn.
Bokeh
Bokeh es una librería que permite generar gráficos interactivos. Los podemos exportar a un documento HTML que podemos compartir con cualquiera que tenga un navegador web.
Es una librería muy útil cuando nos interesa buscar cosas en los gráficos y queremos poder acercarnos y movernos por el gráfico. O cuando queremos compartirlos y dar la posibilidad de explorar los datos a otra persona.
Empezamos importando la librería y definiendo el archivo en el que guardaremos el gráfico:
from bokeh.plotting import figure, output_file, save output_file('popularidad_data_science.html')
Dibujamos lo que queramos y lo guardamos en el archivo:
p = figure(title='popularidad del término data science', x_axis_label='Mes', y_axis_label='popularidad data science') p.line(df['Mes'], df['data science'], legend='popularidad', line_width=2) save(p)
Puedes ver cómo queda el archivo popularidad_data_science.html haciendo clic aquí. Es interactivo, puedes moverte por el gráfico y hacer zoom a tu gusto.
Añadir varios gráficos a un mismo archivo:
output_file('graficos_multiples.html') s1 = figure(width=250, plot_height=250, title='data science') s1.circle(df['Mes'], df['data science'], size=10, color='navy', alpha=0.5) s2 = figure(width=250, height=250, x_range=s1.x_range, y_range=s1.y_range, title='machine learning') #share both axis range s2.triangle(df['Mes'], df['machine learning'], size=10, color='red', alpha=0.5) s3 = figure(width=250, height=250, x_range=s1.x_range, title='deep learning') #share only one axis range s3.square(df['Mes'], df['deep learning'], size=5, color='green', alpha=0.5) p = gridplot([[s1, s2, s3]]) save(p)
Puedes ver cómo queda el archivo graficos_multiples.html haciendo clic aquí.
Galería de ejemplos:
En este enlace https://docs.bokeh.org/en/latest/docs/gallery.html se pueden ver ejemplos de todo lo que se puede hacer con Bokeh.
Altair
Altair en mi opinión no aporta nada nuevo respecto a lo que ya hemos comentado anteriormente con las otras librerías y por eso no voy a hablar de ella en profundidad. Quiero hacer mención a esta librería porque puede ser que en su galería de ejemplos encontremos algún gráfico concreto que nos pueda ayudar.
Galería de ejemplos:
En este enlace se pueden ver ejemplos de todo lo que se puede hacer con Bokeh.
Folium
Folium es una librería que nos permite dibujar mapas, marcadores y también podemos dibujar nuestros datos sobre ellos. Folium nos deja elegir el proveedor de mapas, esto nos determina el estilo y la calidad del gráfico. En este artículo, por simplicidad, solo vamos a ver a OpenStreetMap como proveedor de mapa.
El tema de los mapas es bastante complejo y se merece su propio artículo. Aquí solo vamos a ver lo más básico y dibujaremos un par de mapas con los datos que tenemos.
Empecemos por lo más básico, dibujamos un mapa simple sin nada encima.
import folium m1 = folium.Map(location=[41.387, 2.172659], tiles='openstreetmap', zoom_start=18) m1.save('mapa1.html')
Generamos un archivo interactivo para el mapa en el que te puedes mover y hacer zoom a tu gusto. Lo puedes ver aquí.
Podemos añadir marcadores al mapa:
m2 = folium.Map(location=[41.387, 2.172659], tiles='openstreetmap', zoom_start=16) folium.Marker([41.387, 2.172659], popup='<i>Puedes usar el código HTML que quieras</i>', tooltip='click aquí').add_to(m2) folium.Marker([41.387, 2.174], popup='<b>Puedes usar el código HTML que quieras</b>', tooltip='aquí no cliques').add_to(m2) m2.save('mapa2.html')
Puedes ver el archivo interactivo del mapa en el que puedes clicar sobre los marcadores haciendo clic aquí.
En el dataset presentado al principio, tenemos nombres de países y la popularidad de los términos de inteligencia artificial. Tras una visualización rápida se ve que hay países en los que falta uno de estos valores. Vamos a eliminar estos países para hacerlo más fácil. Después utilizaremos Geopandas para transformar los nombres de los países en coordenadas que podremos dibujar sobre el mapa.
from geopandas.tools import geocode df2 = pd.read_csv('mapa.csv') df2.dropna(axis=0, inplace=True) df2['geometry'] = geocode(df2['País'], provider='nominatim')['geometry'] #Puede tardar un rato porque descarga muchos datos. df2['Latitud'] = df2['geometry'].apply(lambda l: l.y) df2['Longitud'] = df2['geometry'].apply(lambda l: l.x)
Ahora que tenemos los datos codificados en latitud y longitud, vamos a representarlos sobre el mapa. Empezamos con un BubbleMap en el que dibujaremos círculos sobre los países. Su tamaño dependerá de la popularidad del término y su color será rojo o verde según si su popularidad está por encima de un valor o no.
m3 = folium.Map(location=[39.326234,-4.838065], tiles='openstreetmap', zoom_start=3) def color_producer(val): if val <= 50: return 'red' else: return 'green' for i in range(0,len(df2)): folium.Circle(location=[df2.iloc[i]['Latitud'], df2.iloc[i]['Longitud']], radius=5000*df2.iloc[i]['data science'], color=color_producer(df2.iloc[i]['data science'])).add_to(m3) m3.save('mapa3.html')
Puedes ver el archivo interactivo del mapa haciendo clic aquí.
¿Y si estoy trabajando con un tipo de datos que necesita una visualización muy concreta?
Por supuesto estas no son todas las librerías de visualización que existen, hay muchas más librerías genéricas de las que no he hablado y además hay librerías para visualizar tipos de datos concretos (como hemos visto Folium para los mapas).
En estos dos enlaces puedes ver una recopilación de librerías de visualización de todo tipo. Aquí podrás encontrar qué has de usar para los datos con los que estás trabajando, y si no lo encuentras… Google es tu amigo!
¿Qué librería utilizar en cada momento?
Ante toda esta variedad de librerías te estarás preguntando qué librería es la mejor para tu proyecto. La respuesta rápida es la librería que te permita hacer fácilmente el gráfico que quieras.
Para las fases iniciales de un proyecto, con pandas y pandas profiling haremos una visualización rápida para entender los datos. Si hiciera falta visualizar más información podríamos usar gráficos simples que podemos encontrar en matplotlib como scatterplots o histogramas.
Para fases avanzadas del proyecto, podemos buscar en las galerías de las librerías principales (Matplotlib, Seaborn, Bokeh, Altair) los gráficos que nos gusten y se ajusten al proyecto. Estas gráficas las podremos usar para dar información en informes, hacer informes interactivos, buscar valores concretos, …
Ya sabes lo que dicen, una imagen vale más que mil palabras.