Trucos de formato sencillos para que los gráficos de matplotplib estén listos para presentaciones
Bradley Stephen Shaw MEDIUM
Los gráficos y las tablas son, con diferencia, la mejor forma de comunicar un mensaje a un público. En realidad, no hay dos formas de decirlo: las imágenes son mejores que las palabras. Según a quién le preguntes, una vale más o menos mil que la otra.
Eso no significa que crear una buena visualización sea fácil. Crear una exhibición impactante y atractiva que transmita un mensaje es difícil. Es aún más desafiante si la exhibición se estrena durante una presentación en vivo: el público no solo escucha atentamente lo que se dice (con suerte), sino que también intenta comprender el mensaje detrás del gráfico y, al mismo tiempo, formula preguntas.
Probablemente podría mostrarte un montón de mis propios gráficos que demuestran lo difícil que es hacer uno bueno, pero te ahorraré el trauma. En cambio, en este artículo veremos cómo:
- Crear gráficos de líneas y barras “base”.
- Cambie los títulos y la señalización para mejorar tanto el impacto visual del gráfico como su capacidad para transmitir un mensaje.
- Elimine el desorden para mejorar la legibilidad del gráfico.
- Cambie la apariencia del gráfico para que el mensaje quede realmente claro.
Tomaremos prestados algunos trucos de nuestra última presentación, en la que analizamos cómo el formato pandas
de DataFrames puede mejorar la entrega de mensajes y la narración de historias. Recomiendo (obviamente) leer ese artículo si está interesado en presentar algunas tablas elegantes junto con excelentes gráficos:
Guía completa para formatear DataFrames de Pandas | Hacia la ciencia de datos
Manos a la obra: primero veamos cómo podemos hacer gráficos de líneas bonitos antes de pasar a intentarlo con un gráfico de barras. En ambos casos, vamos a abrazar a nuestro proposito de Año Nuevo interno y usaremos datos (imaginarios) relacionados con el ejercicio y el entrenamiento.
Aparte: los consejos que se dan aquí se relacionan con matplotlib
, mi paquete de referencia para trazar gráficos en Python. Eso no quiere decir que los mismos consejos y trucos no se puedan aplicar o que no se puedan aplicar en otros paquetes como seaborn
, pero es posible que deba realizar algunos ajustes en su enfoque.

Gráficos de líneas
Comenzaremos con gráficos lineales: visualizaciones simples que son excelentes cuando intentamos comunicar tendencias o patrones a lo largo del tiempo .
Los datos
He elaborado algunos datos que reflejan la proporción de participantes en una encuesta imaginaria en la que se preguntaba a hombres de entre 18 y 60 años qué tipo de ejercicio preferían realizar. Los participantes tenían cuatro opciones para elegir: correr, montar en bicicleta, nadar y un régimen mixto.
Aparte: cuando digo “conjuré algunos datos”, en realidad quiero decir “creé datos de muestra en Excel”.
Preparémonos y echemos un vistazo a los datos:
# funcionalidad
importar pandas como pd
importar numpy como np
importar os
importar matplotlib.pyplot como plt
importar matplotlib.dates como mdates
importar matplotlib.ticker como mtick
# datos importar
ubicación_archivo = r'C:\Users\...\Charts'
nombre_archivo = r'data.csv'
df = pd.read_csv(os.path.join(ubicación_archivo,nombre_archivo))
# convertir columna de fecha a fecha y hora
df[ 'Fecha' ] = pd.to_datetime(df[ 'Fecha' ], formato = '%d/%m/%Y' )
# establecer columna de fecha a índice
df.set_index( 'Fecha' ,inplace = True )
df

Se trata de un conjunto de datos bastante simple. Empecemos por algún punto y creemos nuestro gráfico «base».
La gráfica de la línea base
No hay nada demasiado elegante aquí, solo un poco de matplotlib
:
# tamaño y configuración del gráfico
fig,ax = plt.subplots(figsize = ( 20 , 7.5 ))
# líneas
para la actividad en df.columns:
plt.plot(df.index,df[activity],marker = '^' ,label = f' {activity} ' )
# formato del eje y
plt.gca().yaxis.set_major_formatter(mtick.PercentFormatter( 1 ,decimals = 0 ))
# añadir título y etiquetas de eje
plt.title( 'Tipos de ejercicio (encuestados, hombres de 18 a 60 años)' )
plt.ylabel( 'Proporción' )
plt.xlabel( 'Fecha de la encuesta' )
# varios - cuadrícula y leyenda
plt.grid(axis = 'both' ,alpha = 0.45 )
plt.legend(loc = 'best' ,ncol = 1 )
# resultados
plt.show()
…lo que da:

Ahora bien, mi nerd interior podría pensar que está perfectamente bien presentar esta visualización. Probablemente diría algo como:
- El título, las etiquetas de los ejes y las entradas de la leyenda se combinan para indicar al lector que este gráfico se relaciona con la proporción de encuestados (hombres, de 18 a 60 años) que participan en un determinado tipo de ejercicio.
- Los datos se están representando a lo largo del tiempo, por lo que probablemente exista alguna tendencia o patrón.
- De hecho, cuando observamos el gráfico, vemos que correr y andar en bicicleta se vuelven menos favorables con el tiempo, mientras que un régimen mixto se está volviendo más popular en esta cohorte.
Por extraño que parezca, ¡es exactamente el mensaje que estamos intentando transmitir! Tenemos que encontrar una forma de transmitirlo sin que el público tenga que hacer tanto esfuerzo.
Por lo general, la mejor manera de hacerlo es simplemente decirle a la audiencia lo que intentas decir. Hagámoslo haciendo que el título sea más útil y recurriendo a un subtítulo solo si agrega valor a la visualización.
Uso de títulos descriptivos
Agregaremos títulos descriptivos a la trama usando el text
comando¹.
Captaremos el mensaje lo más nítido posible:
- El titular (es decir, el título) es que el entrenamiento en régimen mixto se está volviendo más popular con el tiempo.
- El lema (es decir, el subtítulo) es que el aumento de la popularidad del régimen mixto proviene de la disminución de la popularidad del atletismo y el ciclismo.
En términos de código, esto se parece a algo así (formateado para facilitar la lectura):
# plot
fig,ax = plt.subplots(figsize = ( 20 , 7.5 ))
# título informativo + subtítulo
title = 'El entrenamiento mixto está ganando popularidad con el tiempo'
subtitle = 'Los hombres de entre 18 y 60 años están abandonando el running y
el ciclismo en favor de un régimen de entrenamiento mixto'
# añadir título + subtítulo al gráfico
plt.text(
x = 0.125 ,y = 0.90 ,s = title,fontname = 'Arial' ,
fontsize = 20 ,ha= 'left' ,transform = fig.transFigure
)
plt.text(
x = 0.125 ,y = 0.86 ,s = subtitle,fontname = 'Arial' ,
fontsize = 16 ,ha = 'left' ,transform = fig.transFigure
)
# líneas
para la actividad en df.columns:
plt.plot(df.index,df[activity],marker = '^' ,label = f' {actividad} ' )
# formato del eje y
plt.gca().yaxis.set_major_formatter(mtick.PercentFormatter( 1 ,decimals = 0 ))
# etiquetas de eje
plt.ylabel( 'Proporción' )
plt.xlabel( 'Fecha de la encuesta' )
# varios - cuadrícula y leyenda
plt.grid(axis = 'both' ,alpha = 0.45 )
plt.legend(loc = 'best' ,ncol = 1 )
# jugar con el espacio sobre el gráfico
plt.subplots_adjust(top= 0.8 , wspace= 0.3 )
plt.show()
…lo que da:

Yo diría que ya es un gran cambio para mejor, ya que el mensaje está a la vista del lector. El gráfico en sí todavía parece bastante recargado, así que lo abordaremos a continuación.
Aparte: si te preocupas demasiado por los detalles, probablemente te parezca que la diferencia entre los títulos y el gráfico en sí es un poco grande. Tal como está, probablemente tengas razón, pero sigue leyendo: tengo algo planeado para eso más adelante.
Eliminando el desorden
Los gráficos desordenados son difíciles de leer. De hecho, cualquier cosa que desvíe la atención del mensaje del gráfico hace que éste sea más difícil de leer.
En este contexto, el término «desorden» podría significar cualquier cosa: etiquetas de ejes, marcadores, títulos mal ubicados o incluso líneas de cuadrícula. Analizaremos todos estos elementos, pero comenzaremos con el mayor infractor: la leyenda.
La leyenda de un gráfico puede ser bastante controvertida. Por un lado, el pensamiento tradicional es que un buen gráfico contiene una buena leyenda: una que permita al lector distinguir fácilmente entre las distintas cantidades representadas.
Por otra parte, si el lector mira desde el gráfico a la leyenda (y viceversa, probablemente muchas veces), la leyenda es claramente una distracción.
Vamos a llegar a un punto intermedio: cambiaremos la leyenda para que deje de ser un elemento gráfico prácticamente independiente y pase a integrarse en la propia visualización. Para ello, anotaremos cada línea individual.
Así que podemos obtener algo como esto:

No está nada mal: nos hemos deshecho de la leyenda sin perder nada de su utilidad.
Anotar las líneas es bastante sencillo, una vez que lo dominas:
# anotar
plt.annotate(
text = 'En ejecución' ,
xy = (pd.to_datetime( '01-01-2022' ),df[ 'En ejecución' ][- 1 ]),
textcoords = 'puntos de desplazamiento' ,
xytext = ( 5 ,- 4 ),fontname = 'Arial' ,fontsize = 13 ,color = 'tab:blue'
)
Sigo pensando que las líneas de la cuadrícula y los límites de la trama (o “columnas”) son una distracción. Deshacerse de ellos es simple:
# líneas de cuadrícula
# mantener solo líneas verticales atenuadas
plt.grid(axis = 'y' ,alpha = 0.3 )
# desactivar espinas
plt.gca().spines[[ 'left' , 'right' , 'top' ]].set_visible( False )

¡Ya estamos empezando a llegar a ese punto! Al analizarlo, creo que necesitamos más separación entre nuestros títulos y el gráfico en sí. Por eso, agregaremos una línea de separación.
También necesitamos agregar alguna descripción para el eje y. Tal vez hemos sido demasiado implacables al eliminar el «desorden», por lo que agregaremos algo nuevamente allí. También es una buena práctica citar la fuente de información, por lo que agregaremos una nota al pie para hacer precisamente eso.

En cuanto al código, esto fue bastante simple:
# línea entre los títulos y el gráfico
plt.gca().plot(
[ 0.1 , .9 ], # coordenadas x
[ .87 , .87 ], # coordenadas y
transform = fig.transFigure,
clip_on = False ,
color = 'k' ,
linewidth = 1.5
)
#
descripción del eje description = 'Proporción de encuestados (%)'
plt.text(
x = 0.1 ,
y = 0.8 ,
s = description,
fontname = 'Arial' ,
fontsize = 14 ,
ha= 'left' ,
transform = fig.transFigure
)
# nota al pie
footnote = "Fuente: La imaginación de Brad, enero de 2023"
plt.text(
x = 0.1 ,
y = 0.05 ,
s = footnote,
fontname = 'Arial' ,
fontstyle = 'italic' ,
fontsize = 12 ,
ha = 'left' ,
transformar = fig.transFigure
)
Ahora hay un toque final que podemos dar para que el mensaje quede realmente claro: cambiar los colores.
Aunque el gráfico es realmente bonito, las líneas de colores podrían restarle valor al mensaje general. Por eso, para enfatizar el resultado de que el entrenamiento mixto está ganando fuerza con el tiempo, vamos a hacer que la línea de régimen mixto se destaque por:
- Haciéndolo realmente espeso, atrevido y rojo.
- Haciendo que las otras líneas sean grises.

¡Y listo! Un gráfico de gran aspecto, lleno de información y fácil de digerir (si se me permite decirlo).
Gráficos de barras
Los gráficos de barras y columnas se utilizan a menudo para comparar distintas cantidades cuantitativas o cualitativas. Son muy útiles cuando se realizan pocas comparaciones, pero en mi opinión no funcionan muy bien si hay muchas comparaciones que hacer o si se intenta visualizar tendencias a lo largo del tiempo.
Ahora bien, si buscas en Google “gráficos de barras versus gráficos de columnas”, encontrarás toneladas de artículos que explican y describen las diferencias exactas entre ambas visualizaciones.
No lo haré porque, sinceramente, no sé la diferencia. Para un «profesional» como yo, la semántica es una distracción. Lo importante es saber que, en algunas circunstancias, es más útil tener un gráfico con barras horizontales que uno con barras verticales. Veremos un buen ejemplo de esto en un minuto.
Datos
Vamos a crear algunos datos para visualizar. Nuevamente, se tratará de datos relacionados con el fitness, esta vez capturando la proporción de personas que van al gimnasio y que visitan la sala de pesas según la hora del día. Para simplificar las cosas, nuestra variable de «hora del día» se agrupará aproximadamente en cinco categorías.
# data
df = pd.DataFrame(
{
'Hora' :[ 'Temprano en la mañana' , 'Mañana' , 'Mediodía' , 'Tarde' , 'Noche' ],
'Atletas' :[ 0.17 , 0.075 , 0.23 , 0.125 , 0.4 ]
}
)
El gráfico de barras base
Nuevamente, crearemos un gráfico «base» que podemos mejorar. Un simple fragmento de código nos brinda un gráfico bastante estándar, nada especial, pero cumple su función.
# gráfico
fig,ax = plt.subplots(figsize = ( 20 , 7.5 ))
# barras
plt.bar(df[ 'Tiempo' ],df[ 'Atletas' ])
# formato del eje y
plt.gca().yaxis.set_major_formatter(mtick.PercentFormatter( 1 ,decimals = 0 ))
# línea de cuadrícula
plt.grid(axis = 'y' ,alpha = 0.45 )
# etiquetas y título
plt.title( 'Proporción de atletas entrenando, por hora del día' )
plt.ylabel( 'Proporción' )
plt.xlabel( 'Hora del día' )
plt.show()

Repasemos el gráfico y cambiemos algunas cosas.
En este momento, está bastante claro que la sesión vespertina es el momento más popular para ir al gimnasio. Sin embargo, no resulta inmediatamente obvio cuándo serán los siguientes horarios más populares (o menos populares). Por eso, cambiaremos el orden en el que se dibujan las barras.
Si bien algunas personas prefieren ordenar los valores en orden creciente (es decir, ascending = True
), creo que deberíamos cambiar la orientación del gráfico y trazar los horarios más populares de arriba a abajo.
Las apariencias importan, por eso eliminaremos el desorden del gráfico y aplicaremos un poco de estilo . También agregaremos un poco de estilo de diseño para darle vida a la estética.
Por último, reiteraremos el mensaje que intentamos transmitir cambiando algunos colores.
Vamos a ponernos manos a la obra.
Cambiar la orientación
…y un poco de orden.
No hay nada demasiado especial que destacar aquí. El DataFrame se ha reordenado utilizando sort_values
, y usamos barh
en lugar de bar
para obtener la orientación horizontal.
Esto nos da:

Esto ya está mejor: vea cuánto más fácil es ver los horarios de mayor actividad y hacer comparaciones entre cada franja horaria.
Leer valores exactos en el eje x es un poco complicado, así que lo tendremos en cuenta cuando mejoremos el desorden y el estilo.
Desorden y estilo
Es hora de hacer un poco de cirugía estética: eliminaremos las etiquetas de los ejes, las líneas de la cuadrícula y los lomos, y pondremos a trabajar nuestros títulos. También agregaremos etiquetas de barras para no perder información cuando eliminemos el eje x.
Por supuesto, siempre citamos y atribuimos nuestros datos, por lo que agregaremos una nota a pie de página.
Además de todo eso, haremos algunos cambios estéticos para que el gráfico llame la atención. Dado que no hay una buena razón para que nuestras barras sean tan largas, parte del estilo consistirá en algunos cambios generales de tamaño, pero el cambio más importante provendrá de cambios para enfatizar el mensaje.
Hemos visto cómo hacer la mayoría de los cambios anteriormente, por lo que los próximos pasos tendrán poco código y mostrarán solo conceptos nuevos.
¿Estás listo para el nuevo y mejorado gráfico? ¡Yo lo estoy!

Es un buen avance. Observe cómo el uso de etiquetas de barras nos permite deshacernos por completo del eje x. Es un pequeño cambio de código:
# gráfico
fig,ax = plt.subplots(figsize = ( 20 , 7.5 ))
# agregar barras
bars = plt.barh(df[ 'Tiempo' ],df[ 'Atletas' ],color = 'k' )
# agregar etiquetas
plt.bar_label(
bars,
labels = [ f' {x: .0 %} ' for x in bars.datavalues],
padding = 10 ,
fontsize = 14
)
El gráfico rojo es una combinación de un rectángulo y una línea. Es un poco complicado de armar, pero creo que le agrega un poco de estilo al gráfico, bastante al estilo de The Economist.
# añade un poco de estilo gráfico
# rectángulo primero
plt.gca().add_patch(
plt.Rectangle(
(- 0.05 , .95 ), # ubicación
0.0125 , # ancho
- 0.13 , # altura
facecolor = 'tab:red' ,
transform = fig.transFigure,
clip_on = False ,
linewidth = 0
)
)
# ahora la línea
plt.gca().plot(
[- 0.049 , .95 ], # longitud de la línea
[ .82 , .82 ], # altura
transform = fig.transFigure,
clip_on = False ,
color = 'tab:red' ,
linewidth = 3
)
Por último, pero no por ello menos importante, cambiaremos el color de las barras para dejar claro que la mayoría de la gente juega al golf por la noche.

Este es quizás el cambio más grande en el gráfico y se crea mediante el cambio de código más pequeño: en lugar de utilizar una sola cadena, introducimos una lista de colores en el color
argumento en barh
.
¡Excelente!
Envolverse y pasear
En lo que se está convirtiendo en un mal hábito mío, resumiré y divagaré simultáneamente.
Con algunos ejemplos de gráficos de líneas y barras, hemos visto cómo los títulos descriptivos y los trucos visuales pueden mejorar la transmisión del mensaje del gráfico. También hemos visto cómo eliminar el desorden del gráfico puede hacer que el lector se centre en el mensaje que intentamos transmitir.
Ahora bien, me encantan los gráficos coloridos y no me avergüenza admitirlo (claramente). Pero sí tengo que admitir que atenuar el color y usarlo de manera táctica puede mejorar realmente la capacidad del gráfico para transmitir un mensaje a una audiencia.
Al igual que en una diapositiva de una presentación, es necesario pensar en profundidad qué es lo que el gráfico intenta transmitir y luego darle la mejor oportunidad para que lo haga. Esto puede implicar cambiar los tipos de gráficos, cambiar las paletas de colores, agregar títulos descriptivos o incluso eliminar algunos elementos del gráfico. Al igual que con el diseño de interiores, no tenga miedo de tomar decisiones audaces. Si ocurre lo peor, siempre puede reescribir el código del gráfico.
Si no tienes muchas ideas de diseño, te recomiendo que eches un vistazo a publicaciones como The Economist y Financial Times: suelen ser excelentes para transmitir un mensaje en un gráfico atractivo. He aprendido muchos trucos y consejos sobre programación leyendo la matplotlib
documentación y navegando por varios hilos de StackOverflow.
Mi último consejo, y posiblemente el más importante, es que practiques y luego revises tus gráficos. Mejor aún, haz que otra persona revise tus gráficos y vea si «entiende» el mensaje que intentas comunicar. Suena poco convincente, lo sé, pero ayuda.
Si has llegado hasta aquí, gracias. Espero que hayas disfrutado de la lectura tanto como yo disfruté escribiéndolo (elaborar gráficos ha sido curiosamente catártico). Todavía estoy aprendiendo (y practicando) cómo hacer mejores gráficos, así que cualquier consejo o truco será muy apreciado.
Referencias y recursos
Algunos fragmentos de documentación oficial que me hicieron la vida más fácil: