Cómo crear hermosos gráficos de barras con Seaborn y Matplotlib (incluyendo animación)
Create beautiful bar charts with Seaborn and Matplotlib (including animation).
Tutorial de Gráficos
Un tutorial de visualización de datos para Python

Hola y bienvenido a mi primer tutorial de Matplotlib y Seaborn. Hoy, te mostraré cómo convertir un gráfico de barras predeterminado en una visualización impresionante con iconos y animación.
Házmelo saber si te gusta este tipo de contenido. Si es así, ¡puedo crear más del mismo! 🙂
Puedes encontrar el código y los datos preprocesados en este repositorio: simple-bar-chart-tutorial.
Empecemos.
Paso 1: Creando un gráfico de barras predeterminado
Para este tutorial, he creado un conjunto de datos simple con el número total de estrellas a lo largo del tiempo para tres marcos populares de aprendizaje profundo de código abierto (Tensorflow
, PyTorch
y Keras
).
- Mapeo hacia Adelante y hacia Atrás para Visión por Computadora
- Conoce a LieGAN Un Marco de Inteligencia Artificial que Utiliza el ...
- Novo Nordisk apoyará a los postdocs del MIT que trabajan en la inte...

Y aquí hay una función simple que crea un gráfico de barras simple para una fila en el DataFrame.
def create_bar_chart(row, color): return sns.barplot( y=row.index.str.capitalize().values, x=row.values, orient="h", saturation=1, color=color, width=0.75, )
Para crear una primera visualización, ejecuto el código anterior de esta manera.
row = df.iloc[-1]fig = plt.figure(figsize=(12, 7))ax = create_bar_chart(row, color=bar_color)plt.title("Número total de estrellas en GitHub")plt.tight_layout()plt.show()
Aquí está el gráfico de barras predeterminado que obtengo si ejecuto esta función para la última fila en el conjunto de datos con el color naranja.

En los siguientes pasos, crearé funciones adicionales que podemos ejecutar junto con el código anterior para mejorar los gráficos.
Intentemos crear algo más hermoso.
Paso 2: Creando un tema
Primero, quiero crear una función que me permita probar diferentes colores y fuentes para mis gráficos.
Hay un montón de métodos tanto en Matplotlib como en Seaborn que te permitirán alterar la apariencia de tus gráficos.
Prefiero primero crear un tema usando sns.set_style()
. Aquí hay un fragmento de código que uso para crear un nuevo tema rápidamente.
def set_seaborn_style(font_family, background_color, grid_color, text_color): sns.set_style({ "axes.facecolor": background_color, "figure.facecolor": background_color, "grid.color": grid_color, "axes.edgecolor": grid_color, "axes.grid": True, "axes.axisbelow": True, "axes.labelcolor": text_color, "text.color": text_color, "font.family": font_family, "xtick.color": text_color, "ytick.color": text_color, "xtick.bottom": False, "xtick.top": False, "ytick.left": False, "ytick.right": False, "axes.spines.left": False, "axes.spines.bottom": True, "axes.spines.right": False, "axes.spines.top": False, })
Hay algunas opciones más para sns.set_style()
, y es posible que desees usarlo de manera diferente. Pero esta es la configuración que mejor funciona para mí.
Para inspirarme y crear una paleta de colores, a menudo visito colorhunt.co o canva.com. Si tengo colores base que me gustan, voy a coolors.co si necesito algunos más.
Aquí está la paleta de colores que creé para este tutorial (y sí, me gusta el morado).

Mi fuente de elección es “PT Mono”, y con esa decisión, puedo ejecutar el siguiente código.
background_color = "#2F195F"grid_color = "#582FB1"bar_color = "#835ED4"text_color = "#eee"set_seaborn_style(font_family, background_color, grid_color, text_color)
Si ahora ejecuto el código original para crear un gráfico de barras, obtengo lo siguiente.

Es una mejora clara, pero no suficiente. Continuemos formateando el texto del título y las etiquetas de los ejes.
Paso 3: Formato de texto
Lo primero que noto es que las etiquetas de los ejes necesitan ser más grandes. Toda la información mostrada en un gráfico debe ser fácil de ver de inmediato.
Y no me gusta la forma en que se ven los números en el eje x. En lugar de escribir 75000, quiero escribir 75K para obtener una apariencia menos intimidante.
Es por eso que creé esta función.
def format_axes(ax): ax.tick_params("x", labelsize=20, pad=16) ax.tick_params("y", labelsize=20, pad=8) plt.xticks( ticks=ax.get_xticks()[:-1], labels=["{}K".format(int(x / 1000)) for x in ax.get_xticks()[:-1]] )
Para el título, agrego parámetros para aumentar el tamaño de la fuente y ajustar la posición.
Aquí está el código para crear el gráfico con mis nuevas modificaciones.
row = df.iloc[-1]fig = plt.figure(figsize=(12, 7))ax = create_bar_chart(row, color=bar_color)# Nueva funciónformat_axes(ax)plt.title("Número total de estrellas en GitHub", fontsize=34, y=1.2, x=0.46)plt.tight_layout()plt.show()
Y aquí está el resultado.

Está empezando a verse bastante bien, pero ahora es hora de agregar un poco de magia con iconos.
Paso 4: Agregar iconos
Agregar imágenes e iconos a los gráficos es divertido pero complicado. No siempre es fácil colocarlos en la ubicación perfecta o con el tamaño ideal.
La siguiente función agrega iconos al final de cada barra en mi gráfico utilizando xycoords="data"
y los valores de mi DataFrame.
El parámetro boxstyle
dentro de bboxprops
crea un fondo circular blanco.
def add_bar_icons(ax, row, background_color, zoom, pad): for index, (name, value) in enumerate(row.items()): icon = plt.imread("./icons/{}.png".format(name.lower())) image = OffsetImage(icon, zoom=zoom, interpolation="lanczos", resample=True, visible=True) image.image.axes = ax ax.add_artist(AnnotationBbox( image, (value, index), frameon=True, xycoords="data", bboxprops={ "facecolor": "#fff", "linewidth": 3, "edgecolor": background_color, "boxstyle": "circle, pad={}".format(pad), } ))
Quiero poner el icono en un círculo blanco y agregar un borde del mismo color morado oscuro que el fondo del gráfico.
Hasta ahora, no he encontrado una buena manera de manejar el parámetro zoom
dinámicamente, así que lo ajusto manualmente para obtener los tamaños correctos.
Ahora mi código para crear el gráfico se ve así.
row = df.iloc[-1]fig = plt.figure(figsize=(12, 7))ax = create_bar_chart(row, color=bar_color)# Nuevas funcionesformat_axes(ax)add_bar_icons(ax, row, background_color, zoom=0.09, pad=0.9)plt.title("Número total de estrellas en GitHub", fontsize=34, y=1.2, x=0.46)plt.tight_layout()plt.show()
Y esto es lo que obtengo.

Para agregar la estrella, he creado otra función que agrega un icono personalizado en cualquier lugar del gráfico usando xycoords="axes fraction"
.
def add_icon(ax, icon_name, x, y, zoom): icon = plt.imread("./icons/{}.png".format(icon_name)) image = OffsetImage(icon, zoom=zoom, interpolation="lanczos", resample=True, visible=True) image.image.axes = ax ax.add_artist(AnnotationBbox( image, (x, y), frameon=False, xycoords="axes fraction", ))
En este próximo paso, hago espacio para el icono de la estrella agregando espacios adicionales al título y ajustando los parámetros x
e y
para colocar el icono en la ubicación correcta.
row = df.iloc[-1]fig = plt.figure(figsize=(12, 7))ax = create_bar_chart(row, color=bar_color)# Nuevas funcionesformat_axes(ax)add_bar_icons(ax, row, background_color, zoom=0.09, pad=0.9)add_icon(ax, "star", x=0.46, y=1.26, zoom=0.13)plt.title("Número total de estrellas en GitHub", fontsize=34, y=1.2, x=0.46)plt.tight_layout()plt.show()
Ahora nuestro gráfico de barras se ve así, y casi hemos terminado.

Se ve excelente, pero ahora quiero convertir el gráfico en un formato más versátil.
Y hagamos algo al respecto de ese aspecto apretado agregando algo de relleno.
Paso 5: Convertir el gráfico en una imagen
Para esta parte, he creado una función que toma la figura y la convierte en una imagen PIL. Una imagen PIL es más fácil de trabajar para los últimos pasos de nuestro tutorial.
def create_image_from_figure(fig): plt.tight_layout() fig.canvas.draw() data = np.frombuffer(fig.canvas.tostring_rgb(), dtype=np.uint8) data = data.reshape((fig.canvas.get_width_height()[::-1]) + (3,)) plt.close() return Image.fromarray(data)
También he creado la siguiente función para agregar relleno alrededor del gráfico.
def add_padding_to_chart(chart, left, top, right, bottom, background): size = chart.size image = Image.new("RGB", (size[0] + left + right, size[1] + top + bottom), background) image.paste(chart, (left, top)) return image
Aquí hay una nueva versión del código para generar el gráfico donde he reemplazado el plt.show()
estándar con nuestros nuevos métodos.
row = df.iloc[-1]fig = plt.figure(figsize=(12, 7))ax = create_bar_chart(row, color=bar_color)\plt.title("Número total de estrellas en GitHub", fontsize=34, y=1.2, x=0.46)# Nuevas funcionesformat_axes(ax)add_bar_icons(ax, row, background_color)add_icon(ax, "star", 0.46, 1.26)image = create_image_from_figure(fig)image = add_padding_to_chart(image, 0, 10, 10, 10, background_color)
Y aquí está el resultado.

¡Fantástico!
Ahora hemos convertido el gráfico de barras predeterminado en algo mucho más hermoso.
Terminemos con una sección de bonificación.
Bono: Creación de una animación
Como hemos separado el código en funciones reutilizables, es bastante fácil crear una animación.
Todo lo que tenemos que hacer es ejecutar el código varias veces con diferentes valores y unir los fotogramas.
Aquí hay un bucle for donde tomo las últimas 200 filas de las 2000 del conjunto de datos. También estoy arreglando el eje x estableciendo xlim=(0, 185000)
para evitar valores parpadeantes.
images = []for i in tqdm.tqdm(range(1, 2000, 10)): row = df.iloc[-i] fig = plt.figure(figsize=(12, 7)) ax = create_bar_chart(row, color=bar_color) ax.set(xlim=(0, 185000)) plt.title("Número total de estrellas en GitHub", fontsize=34, y=1.2, x=0.46) format_axes(ax) add_bar_icons(ax, row, background_color, zoom=0.09, pad=0.9) add_icon(ax, "star", 0.46, 1.26) image = create_image_from_figure(fig) image = add_padding_to_chart(image, 20, 20, 40, 0, background_color) images.append(image) images.reverse()
A continuación, uso imageio
para crear un GIF.
# Agregando algunas copias del último fotograma para crear un retrasoimages = images + [images[-1] for _ in range(20)]imageio.mimwrite('./animation.gif', images, duration=50)
Aquí está el resultado.

Eso marca el final de este tutorial, y espero que te haya gustado. Si es así, comparte esta historia y suscríbete a mi canal.
También deberías seguirme en Twitter: @oscarle3o
Gracias por leer.
¡Nos vemos la próxima vez! 🙂