Existen varias librerías populares de visualización de datos, siendo la principal matplotlib
matplotlib permite a través de la programación crear todo tipo de gráficas y personalizar cualquiera de sus aspectos.¶Podéis encontrar muchos ejemplos en @matplotlib
Nosotros veremos unos principios básicos, y recurriremos a algunas funciones de visualización en
pandasasí como a la libreríaseabornambas construidas conmatplotlibpero que facilitan la exploración rápida de conjuntos de datos.
Un recurso muy útil: las "cheatsheets" oficiales de `matplotlib', disponibles en: https://github.com/matplotlib/cheatsheets/
matplotlib¶matplotlib presenta una jerarquía de los distintos elementos de una gráfica:
Sus elementos principales son:
figure: la figura completa que puede contener diferentes gráficasaxes: lo que normalmente entendemos por gráfica.axis: los ejes de cada gráficaartist: todo lo que se ve en una figura es un artist, incluso figure, axes, axis.matplotlib¶from matplotlib import pyplot as plt
figure y su o sus axes (gráficas)¶Para ello, usaremos la instrucción subplots
fig, ax = plt.subplots()
Podemos especificar una matriz de axes: por ejemplo una fila y dos columnas
fig, axs = plt.subplots(1, 2)
Ahora añadimos elementos al objeto ax o a cada componente de axs, axs[0] o axs[1], aplicandoles métodos, por ejemplo, añadiendo un título:
fig, axs = plt.subplots(1, 2)
axs[0].set_title("Primera gráfica");
Consideremos unos datos sencillos
import pandas as pd
df = pd.DataFrame({
'col1': [3, 1, 5],
'col2': [2, 4, 6],
'col3': ['a', 'b', 'c'],
'col4': ['Hombre', 'Mujer', 'Hombre'],
'col5': [100, 300, 200]
}
)
df.sort_values('col1', inplace=True)
Vamos a crear un figure con un único axes, y representar col2 en función de col1
fig, ax = plt.subplots()
ax.plot(df['col1'], df['col2']);
En la gráfica representada
fig, ax = plt.subplots()
ax.plot(df['col1'], df['col2']);
El método plot representa líneas que unen los puntos por orden de aparición en los vectores df['col1'] y df['col2'].
Otros métodos que se aplican a un axes representan otros tipos de gráficas:
fig, ax = plt.subplots(figsize=(4, 3))
ax.scatter(df['col1'], df['col2']);
fig, ax = plt.subplots(figsize=(4, 3))
ax.bar(df['col1'], df['col2']);
fig, ax = plt.subplots(figsize=(4, 3))
ax.fill(df['col1'], df['col2']);
fig, ax = plt.subplots(figsize=(4,3))
ax.fill_between(df['col1'], df['col2']);
fig, ax = plt.subplots()
ax.scatter(df['col1'], df['col2'], color='red');
El control de los colores en
matplotlibes muy extenso, por una parte, se puede consultar la lista de nombres de colores soportados en https://matplotlib.org/3.3.3/gallery/color/named_colors.html Por otra parte, se pueden usar "colormaps", para disponer de colores de variación uniforme. Más información más adelante.
fig, ax = plt.subplots(figsize=(4, 3))
ax.scatter(df['col1'], df['col2'], marker='P');
Ver los marcadores posibles en la cheatsheet: https://github.com/matplotlib/cheatsheets/ de la que está extraida la siguiente imagen:
Extraido de la cheatsheet https://github.com/matplotlib/cheatsheets/:
fig, ax = plt.subplots(figsize=(4, 3))
ax.plot(df['col1'], df['col2'], linestyle='--', linewidth=3);
fig, ax = plt.subplots(figsize=(4, 3))
ax.plot(df['col1'], df['col2'], linestyle='--', marker='P');
Para ello, existen una gran variedad de métodos que se aplican a figure o axes o a sus elementos.
Nos fijamos por ejemplo en los básicos mencionados en la cheatsheet
ax.grid() # Para añadir una rejilla
ax.set_xlim(vmin, vmax) # fija los límites del eje Ox, igual para set_ylim
ax.set_xlabel(label) # Establece la etiqueta del eje Ox, igual para Oy
ax.set_xticks(list) # indica en qué valores debe aparecer "ticks" en Ox, igual para Oy
ax.set_ticklabels(list) # indica las etiquetas de los "ticks" en Ox, igual en Oy
ax.set_title(title) # Indica el título de la gráfica
ax.set_tick_params(width=10) # fija diferentes parámetros por ejemplo rotation, se puede especificar axis
Para evitar solapamientos en las etiquetas de los ejes, los títulos, etc... podemos usar el método tight_layout que se aplica a un axes concreto o a todo un figure.
fig.tight_layout() # también podría ser ax.tight_layout()
El patch es un rectángulo de un elemento geométrico con color de fondo y color de borde. Tanto figure como axes tienen patch. Podemos usar los métodos set_facecolor, set_edgecolor y set_alpha sobre un patch:
fig.patch.set_facecolor('green') # El patch
colormaps) en matplotlib¶Muy a menudo necesitamos un conjunto de colores para distinguir grupos de datos en la gráfica. matplotlib proporciona muchos mapas de colores diseñados para permitir visualizar de manera fidedigna la variación de una o varias cantidades.
Se puede encontrar información detallada en https://matplotlib.org/3.3.0/tutorials/colors/colormaps.html y la cheatsheet presenta varios de los mapas de colores más comunes
Si represento datos en una gráfica que corresponden a dos grupos diferentes, es bueno distinguirlos con colores diferentes o/y tipos de líneas diferentes, marcadores diferentes.
Por una parte, poder añadir tantos ax.plot, ax.scatter etc, como grupos:
import pandas as pd
import numpy as np
rng = np.random.default_rng(314)
df = pd.DataFrame({'H': 2 * rng.integers(low=0, high=2, size=100) - 1,
'M': 2 * rng.integers(low=0, high=2, size=100) - 1}).cumsum()
fig, ax = plt.subplots()
ax.step(df.index.values, df['H'])
ax.step(df.index.values, df['M']);
matplotlib se ha encargado de cambiar de color para cada plot.
Para que sea más informativo, puedo añadir una etiqueta a cada serie representada y generar una leyenda:
fig, ax = plt.subplots()
ax.step(df.index.values, df['H'], label='Hombre')
ax.step(df.index.values, df['M'], label='Mujer')
ax.legend();
A medida que voy añadiendo elementos, matplotlib recorre un ciclo de colores que por defecto es el siguiente: (imagen extraida de https://matplotlib.org/3.2.1/users/dflt_style_changes.html#colors-in-default-property-cycle)
También es posible especificar el color en cada serie, por supuesto
fig, ax = plt.subplots()
ax.step(df.index.values, df['H'], label='Hombre', color='red')
ax.step(df.index.values, df['M'], label='Mujer', color='blue')
ax.legend();
A menudo usamos el color para visualizar la variación de una variable, podéis pensar en un "heatmap" por ejemplo. (Fuente: http://www.wright.edu/~oleg.paliy/Papers/PCR_modeling/FigureS5.png)
Veamos cómo hacerlo en un scatter plot:
x = rng.standard_normal(size=300)
y = rng.standard_normal(size=300) * 3
z = rng.random(300)
fig, ax = plt.subplots()
p = ax.scatter(x, y, c=z);
Podemos añadir una barra de colores (colorbar):
fig, ax = plt.subplots()
p = ax.scatter(x, y, c=z)
fig.colorbar(p, ax=ax);
El mapa de colores que ha usado matplotlib por defecto es viridis
Ha mapeado el rango de valores que toma la variable z con el rango de colores de viridis. El mínimo de z está asociado con el lila oscuro, mientras que el máximo está asociado con amarillo. El color de cualquier punto en medio está interpolado.
Probad a cambiar el colormap, añadiendo el parámetro
cmapenax.scatter, por ejemplo,cmap='Spectral'
Hemos visto que scatter tenía un parámetro cmap, pero hay ocasiones en que queremos usar los colores de un colormap en otros contextos.
Empezamos por recuperar un colormap, por ejemplo inferno
clmap = plt.cm.get_cmap('inferno')
Hemos de ser conscientes de lo siguiente:
inferno es 256.clmap que hemos definido realiza el mapeo se hace desde el intervalo de 0 a 1 hacia los colores del colormap.clmap el vector de n valores repartidos uniformemente entre 0 y 1. Puedo construir este vector con np.linspace(0, 1, n)Podemos usar estos colores en cualquier elemento gráfico de un ax. Por ejemplo, supongamos que tenemos 15 series de caminatas aleatorias que recogemos en una lista
series = [ np.cumsum(2 * rng.integers(low=0, high=2, size=100) - 1) for i in range(15)]
Vamos a representarlas, con funciones step y añadiendo una leyenda
fig, ax = plt.subplots(figsize=(15, 15))
for i, s in enumerate(series):
ax.step(np.arange(0, 100), s, label=f'Serie {i}')
ax.legend()
Creamos un vector de colores, usando el colormap que hemos escogido:
colores = clmap(np.linspace(0, 1, 20))
fig, ax = plt.subplots(figsize=(15, 15))
for i, s in enumerate(series):
ax.step(np.arange(0, 100), s, label=f'Serie {i}', color=colores[i])
ax.legend()
En este caso, clmap está basado en los 8 primeros colores del colormap 'Spectral'.