Skip to content

Matplotlib Legend: Guía completa para agregar y personalizar leyendas

Updated on

Un gráfico sin leyenda obliga a los lectores a adivinar qué línea es cuál. Emparejan colores mentalmente, leen mal los datos y sacan conclusiones incorrectas. Agregar una leyenda con plt.legend() es simple -- pero controlar dónde aparece, cómo se ve y evitar que cubra tus datos requiere más trabajo del que la mayoría de los tutoriales muestran.

Esta guía cubre todo, desde la creación básica de leyendas hasta la personalización avanzada: colocación dentro y fuera del gráfico, diseños multicolumna, handles personalizados y leyendas para figuras complejas.

📚

Leyenda básica

Etiquetas automáticas

import matplotlib.pyplot as plt
import numpy as np
 
x = np.linspace(0, 10, 100)
 
plt.plot(x, np.sin(x), label='sin(x)')
plt.plot(x, np.cos(x), label='cos(x)')
plt.legend()
plt.show()

El parámetro label en plot() define lo que aparece en la leyenda. Llama a plt.legend() para mostrarla.

Estilo orientado a objetos

import matplotlib.pyplot as plt
import numpy as np
 
x = np.linspace(0, 10, 100)
 
fig, ax = plt.subplots(figsize=(8, 5))
ax.plot(x, np.sin(x), label='sin(x)')
ax.plot(x, np.cos(x), label='cos(x)')
ax.legend()
plt.show()

Colocación de la leyenda

Usando el parámetro loc

import matplotlib.pyplot as plt
import numpy as np
 
x = np.linspace(0, 10, 100)
 
fig, ax = plt.subplots(figsize=(8, 5))
ax.plot(x, np.sin(x), label='sin(x)')
ax.plot(x, np.cos(x), label='cos(x)')
 
# Ubicaciones comunes
ax.legend(loc='upper right')   # Predeterminado
# ax.legend(loc='upper left')
# ax.legend(loc='lower right')
# ax.legend(loc='lower left')
# ax.legend(loc='center')
# ax.legend(loc='best')  # Selecciona automáticamente el lugar con menos superposición
plt.show()

Todas las opciones de loc

Cadena locNúmero loc
'best'0
'upper right'1
'upper left'2
'lower left'3
'lower right'4
'right'5
'center left'6
'center right'7
'lower center'8
'upper center'9
'center'10

Posicionamiento preciso con bbox_to_anchor

import matplotlib.pyplot as plt
import numpy as np
 
x = np.linspace(0, 10, 100)
 
fig, ax = plt.subplots(figsize=(8, 5))
ax.plot(x, np.sin(x), label='sin(x)')
ax.plot(x, np.cos(x), label='cos(x)')
ax.plot(x, np.sin(x) + np.cos(x), label='sin(x) + cos(x)')
 
# Posicionar leyenda en coordenadas específicas (x, y) en fracción de ejes
ax.legend(loc='upper left', bbox_to_anchor=(0.02, 0.98))
plt.show()

Leyenda fuera del gráfico

Cuando la leyenda superpone datos, muévela fuera:

import matplotlib.pyplot as plt
import numpy as np
 
x = np.linspace(0, 10, 100)
 
fig, ax = plt.subplots(figsize=(10, 5))
for i in range(6):
    ax.plot(x, np.sin(x + i * 0.5), label=f'Phase {i}')
 
# Colocar leyenda a la derecha del gráfico
ax.legend(loc='center left', bbox_to_anchor=(1.0, 0.5))
plt.tight_layout()
plt.show()
import matplotlib.pyplot as plt
import numpy as np
 
x = np.linspace(0, 10, 100)
 
fig, ax = plt.subplots(figsize=(8, 6))
for i in range(5):
    ax.plot(x, np.sin(x + i), label=f'Series {i+1}')
 
# Colocar leyenda debajo del gráfico
ax.legend(loc='upper center', bbox_to_anchor=(0.5, -0.1), ncol=5)
plt.tight_layout()
plt.show()

Estilo de la leyenda

Tamaño de fuente y marco

import matplotlib.pyplot as plt
import numpy as np
 
x = np.linspace(0, 10, 100)
 
fig, ax = plt.subplots(figsize=(8, 5))
ax.plot(x, np.sin(x), label='sin(x)')
ax.plot(x, np.cos(x), label='cos(x)')
 
ax.legend(
    fontsize=12,
    frameon=True,          # Mostrar borde (predeterminado True)
    framealpha=0.8,        # Transparencia del borde
    facecolor='lightyellow',  # Color de fondo
    edgecolor='gray',      # Color del borde
    shadow=True,           # Sombra
)
plt.show()

Diseño multicolumna

import matplotlib.pyplot as plt
import numpy as np
 
x = np.linspace(0, 10, 100)
 
fig, ax = plt.subplots(figsize=(10, 5))
for i in range(8):
    ax.plot(x, np.sin(x + i * 0.4), label=f'Signal {i+1}')
 
# 4 columnas para leyenda compacta
ax.legend(ncol=4, loc='upper center', fontsize=9)
plt.show()

Título de la leyenda

import matplotlib.pyplot as plt
import numpy as np
 
x = np.linspace(0, 10, 100)
 
fig, ax = plt.subplots(figsize=(8, 5))
ax.plot(x, x**2, label='Quadratic')
ax.plot(x, x**1.5, label='Power 1.5')
ax.plot(x, x, label='Linear')
 
ax.legend(title='Modelos de crecimiento', title_fontsize=13, fontsize=11)
plt.show()

Handles personalizados de leyenda

Entradas manuales de leyenda

import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
import matplotlib.lines as mlines
import numpy as np
 
fig, ax = plt.subplots(figsize=(8, 5))
 
# Plotear sin etiquetas
ax.scatter(np.random.randn(50), np.random.randn(50), c='blue', s=20)
ax.scatter(np.random.randn(50) + 2, np.random.randn(50), c='red', s=20)
 
# Crear handles personalizados
blue_patch = mpatches.Patch(color='blue', label='Grupo A')
red_patch = mpatches.Patch(color='red', label='Grupo B')
line_handle = mlines.Line2D([], [], color='green', linestyle='--', label='Umbral')
 
ax.legend(handles=[blue_patch, red_patch, line_handle])
plt.show()

Leyenda para diagrama de dispersión con mapeo de colores

import matplotlib.pyplot as plt
import numpy as np
 
fig, ax = plt.subplots(figsize=(8, 5))
 
categories = ['A', 'B', 'C']
colors = ['#e74c3c', '#3498db', '#2ecc71']
 
for cat, color in zip(categories, colors):
    x = np.random.randn(30)
    y = np.random.randn(30)
    ax.scatter(x, y, c=color, label=f'Categoría {cat}', alpha=0.7, s=50)
 
ax.legend()
plt.show()

Opciones de personalización de leyenda

ParámetroDescripciónEjemplo
locCadena o número de posición'upper right', 2
bbox_to_anchorPunto de anclaje (x, y)(1.0, 0.5)
ncolNúmero de columnas3
fontsizeTamaño del texto12, 'small'
titleTítulo de la leyenda'My Legend'
frameonMostrar marcoTrue, False
framealphaTransparencia del marco0.8
facecolorColor de fondo'white'
edgecolorColor del borde'gray'
shadowSombraTrue
markerscaleMultiplicador de tamaño de marcador1.5
labelspacingEspacio vertical entre entradas0.5
handlelengthLongitud de la línea de leyenda2.0

Ejemplos prácticos

Leyenda para múltiples tipos de gráficos

import matplotlib.pyplot as plt
import numpy as np
 
x = np.arange(5)
values = [23, 45, 56, 78, 32]
trend = [20, 35, 50, 65, 40]
 
fig, ax = plt.subplots(figsize=(8, 5))
ax.bar(x, values, alpha=0.7, label='Real', color='steelblue')
ax.plot(x, trend, 'ro-', label='Tendencia', linewidth=2)
ax.axhline(y=50, color='green', linestyle='--', label='Objetivo')
 
ax.legend(loc='upper left')
ax.set_xlabel('Trimestre')
ax.set_ylabel('Ingresos ($K)')
plt.show()

Leyendas separadas para ejes dobles

import matplotlib.pyplot as plt
import numpy as np
 
x = np.arange(2020, 2027)
revenue = [100, 120, 115, 140, 160, 175, 200]
employees = [50, 55, 52, 60, 70, 75, 85]
 
fig, ax1 = plt.subplots(figsize=(8, 5))
line1 = ax1.plot(x, revenue, 'b-o', label='Ingresos ($M)')
ax1.set_ylabel('Ingresos ($M)', color='blue')
 
ax2 = ax1.twinx()
line2 = ax2.plot(x, employees, 'r-s', label='Empleados')
ax2.set_ylabel('Empleados', color='red')
 
# Combinar leyendas
lines = line1 + line2
labels = [l.get_label() for l in lines]
ax1.legend(lines, labels, loc='upper left')
plt.show()

Exploración interactiva de datos

Al iterar sobre la estética del gráfico y la colocación de la leyenda, PyGWalker (opens in a new tab) te permite construir visualizaciones interactivas en Jupyter arrastrando columnas -- leyendas, colores y tamaños se generan automáticamente:

import pandas as pd
import pygwalker as pyg
 
df = pd.read_csv('your_data.csv')
walker = pyg.walk(df)

Preguntas frecuentes

¿Cómo agrego una leyenda a un gráfico de Matplotlib?

Agrega label='name' a cada llamada de plot(), scatter() o bar(), luego llama a plt.legend() o ax.legend(). La leyenda usa automáticamente las etiquetas que proporcionaste.

¿Cómo muevo la leyenda fuera del gráfico?

Usa bbox_to_anchor con loc. Para el lado derecho: ax.legend(loc='center left', bbox_to_anchor=(1.0, 0.5)). Para abajo: ax.legend(loc='upper center', bbox_to_anchor=(0.5, -0.1)). Llama a plt.tight_layout() para evitar recortes.

¿Cómo cambio el tamaño de fuente de la leyenda en Matplotlib?

Pasa fontsize a legend(): ax.legend(fontsize=14) o usa tamaños de cadena como 'small', 'medium', 'large'. Para el título: ax.legend(title='Title', title_fontsize=16).

¿Cómo creo una leyenda con múltiples columnas?

Usa el parámetro ncol: ax.legend(ncol=3) crea un diseño de 3 columnas. Esto es útil cuando tienes muchas entradas de leyenda y quieres un diseño horizontal compacto.

¿Cómo elimino el borde de la leyenda?

Establece frameon=False: ax.legend(frameon=False). Para mantener el marco pero hacerlo transparente, usa framealpha=0: ax.legend(framealpha=0).

Conclusión

Las leyendas de Matplotlib comienzan con parámetros label y plt.legend(). Usa loc para posiciones estándar, bbox_to_anchor para mover la leyenda fuera del gráfico, ncol para diseños multicolumna y parámetros de estilo como fontsize, frameon y shadow para personalización. Para gráficos con muchas series, coloca la leyenda fuera del área de ejes y llama a tight_layout() para evitar recortes. Para figuras complejas con ejes dobles, combina los handles de línea manualmente para crear una leyenda unificada.

📚