Gráficos de pastel con Matplotlib
Aprende a crear y personalizar gráficos de pastel en Python con Matplotlib: colores, explosión, donut, etiquetas, leyendas y guardado en archivo.
Los gráficos de pastel dividen un círculo en sectores, donde el ángulo de cada sector es proporcional al valor que representa. Funcionan mejor cuando tienes un número pequeño de categorías (idealmente 2–6) y quieres mostrar cómo cada parte se relaciona con el todo — por ejemplo, la cuota de mercado por producto o la distribución del presupuesto por departamento.
Este capítulo cubre desde un primer gráfico mínimo hasta técnicas avanzadas como gráficos de donut, posicionamiento personalizado de etiquetas y guardado de figuras listas para publicación. Todos los ejemplos usan matplotlib.pyplot, la API estándar de alto nivel.
Instalación y configuración
Si aún no has instalado Matplotlib, ejecuta este comando en tu terminal:
pip install matplotlibCada ejemplo de este capítulo comienza con esta importación:
import matplotlib.pyplot as pltplt es el alias convencional para matplotlib.pyplot. Te da acceso a funciones como plt.pie(), plt.title() y plt.show().
Crear un gráfico de pastel básico
plt.pie() es la función principal. Como mínimo recibe una secuencia de valores numéricos — las proporciones se calculan automáticamente.
import matplotlib.pyplot as plt
labels = ['Desktop', 'Mobile', 'Tablet']
values = [60, 30, 10]
plt.pie(values, labels=labels, autopct='%1.1f%%')
plt.title('Website Visitors by Device')
plt.show()Parámetros clave utilizados aquí:
| Parámetro | Propósito |
|---|---|
values | Datos numéricos; Matplotlib los convierte en proporciones |
labels | Nombres de categorías dibujados junto a cada sector |
autopct | Cadena de formato para las etiquetas de porcentaje; '%1.1f%%' produce 60.0% |
El gráfico comienza a dibujar sectores en sentido antihorario desde la posición de las 3 en punto por defecto. La siguiente sección explica cómo cambiar eso.
Controlar la rotación con startangle
Establecer startangle=90 rota el gráfico completo para que el primer sector comience en la posición de las 12 en punto, que es el punto de partida más natural para la mayoría de los lectores.
import matplotlib.pyplot as plt
labels = ['Desktop', 'Mobile', 'Tablet']
values = [60, 30, 10]
plt.pie(
values,
labels=labels,
autopct='%1.1f%%',
startangle=90,
)
plt.title('Website Visitors by Device')
plt.show()startangle acepta cualquier ángulo en grados, medido en sentido antihorario desde el eje x positivo. Un valor de 90 apunta directamente hacia arriba.
Personalizar los colores
Pasa una lista de códigos de color hexadecimales o colores con nombre al parámetro colors. La lista debe tener al menos tantos elementos como tus datos.
import matplotlib.pyplot as plt
labels = ['Desktop', 'Mobile', 'Tablet']
values = [60, 30, 10]
colors = ['#ff9999', '#66b3ff', '#99ff99']
plt.pie(
values,
labels=labels,
colors=colors,
autopct='%1.1f%%',
startangle=90,
)
plt.title('Website Visitors by Device')
plt.show()También puedes usar cualquiera de los mapas de colores integrados de Matplotlib. Por ejemplo, para obtener tres colores de la paleta tab10:
import matplotlib.pyplot as plt
import matplotlib.cm as cm
labels = ['Desktop', 'Mobile', 'Tablet']
values = [60, 30, 10]
cmap = cm.get_cmap('tab10')
colors = [cmap(i) for i in range(len(values))]
plt.pie(values, labels=labels, colors=colors, autopct='%1.1f%%', startangle=90)
plt.title('Website Visitors by Device')
plt.show()Explotar un sector
El parámetro explode desplaza uno o más sectores hacia afuera para llamar la atención sobre ellos. Toma una tupla de valores flotantes, uno por sector. Un valor de 0.1 desplaza un sector un 10 % del radio del gráfico.
import matplotlib.pyplot as plt
labels = ['Desktop', 'Mobile', 'Tablet']
values = [60, 30, 10]
colors = ['#ff9999', '#66b3ff', '#99ff99']
explode = (0.1, 0, 0) # offset the first slice (Desktop) only
plt.pie(
values,
labels=labels,
colors=colors,
explode=explode,
autopct='%1.1f%%',
startangle=90,
shadow=True, # drop shadow for depth
)
plt.title('Website Visitors by Device')
plt.show()Establecer shadow=True añade una sombra sutil que enfatiza aún más el sector explodido.
Añadir un título y una leyenda
Usa plt.title() para el título del gráfico y plt.legend() para un cuadro de leyenda separado. Una leyenda es útil cuando el texto de las etiquetas es largo o cuando los sectores son demasiado pequeños para etiquetarlos claramente.
import matplotlib.pyplot as plt
labels = ['Desktop', 'Mobile', 'Tablet']
values = [60, 30, 10]
colors = ['#ff9999', '#66b3ff', '#99ff99']
plt.pie(
values,
labels=labels,
colors=colors,
autopct='%1.1f%%',
startangle=90,
)
plt.title('Website Visitors by Device')
plt.legend(title='Device type', loc='lower right')
plt.show()loc acepta cadenas de posición estándar como 'upper right', 'lower left' y 'center'. También puedes proporcionar una tupla bbox_to_anchor para una colocación precisa a nivel de píxel.
Controlar la distancia de las etiquetas
Dos parámetros controlan qué tan lejos se sitúan las etiquetas del centro del gráfico:
labeldistance— distancia de la etiqueta de categoría desde el centro, como fracción del radio. El valor por defecto es1.1(justo fuera del sector).pctdistance— distancia de la etiqueta de porcentaje autopct desde el centro. El valor por defecto es0.6(dentro del sector).
import matplotlib.pyplot as plt
labels = ['Desktop', 'Mobile', 'Tablet']
values = [60, 30, 10]
plt.pie(
values,
labels=labels,
autopct='%1.1f%%',
startangle=90,
labeldistance=1.2, # push category labels further out
pctdistance=0.75, # move percentages slightly outward from center
)
plt.title('Website Visitors by Device')
plt.show()Aumenta pctdistance cuando los sectores son grandes y la posición por defecto se ve saturada; redúcelo cuando tienes muchos sectores pequeños.
Crear un gráfico de donut
Un gráfico de donut es un gráfico de pastel con un agujero en el centro. Usa el parámetro wedgeprops para establecer un ancho de anillo, expresado como fracción del radio. Por ejemplo, width=0.5 deja el 50 % del radio como el agujero.
import matplotlib.pyplot as plt
labels = ['Desktop', 'Mobile', 'Tablet']
values = [60, 30, 10]
colors = ['#ff9999', '#66b3ff', '#99ff99']
plt.pie(
values,
labels=labels,
colors=colors,
autopct='%1.1f%%',
startangle=90,
pctdistance=0.85,
wedgeprops=dict(width=0.5), # ring width = 50 % of radius
)
plt.title('Website Visitors by Device')
plt.show()Los gráficos de donut son populares porque el centro vacío proporciona espacio para un recuento total o una métrica resumen, que puedes añadir con plt.text(0, 0, 'Total\n100', ha='center', va='center', fontsize=14).
Varios gráficos de pastel uno al lado del otro
Usa plt.subplots() para colocar dos o más gráficos de pastel en la misma figura. Cada llamada a ax.pie() apunta a su propio objeto de ejes.
import matplotlib.pyplot as plt
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 5))
# --- Chart 1: this month ---
labels = ['Desktop', 'Mobile', 'Tablet']
values_this_month = [60, 30, 10]
ax1.pie(values_this_month, labels=labels, autopct='%1.1f%%', startangle=90)
ax1.set_title('This Month')
# --- Chart 2: last month ---
values_last_month = [70, 20, 10]
ax2.pie(values_last_month, labels=labels, autopct='%1.1f%%', startangle=90)
ax2.set_title('Last Month')
fig.suptitle('Website Visitors by Device', fontsize=14)
plt.tight_layout()
plt.show()fig.suptitle() añade un título por encima de todos los subgráficos. plt.tight_layout() evita que las etiquetas se superpongan entre gráficos.
Guardar un gráfico de pastel en un archivo
Reemplaza plt.show() con plt.savefig() para escribir el gráfico en disco en lugar de mostrarlo en una ventana. Esto es esencial para scripts que se ejecutan en servidores sin interfaz gráfica o para generar recursos de informes.
import matplotlib.pyplot as plt
labels = ['Desktop', 'Mobile', 'Tablet']
values = [60, 30, 10]
plt.pie(values, labels=labels, autopct='%1.1f%%', startangle=90)
plt.title('Website Visitors by Device')
plt.savefig('pie_chart.png', dpi=150, bbox_inches='tight')Opciones comunes de savefig():
| Opción | Efecto |
|---|---|
dpi=150 | Resolución en puntos por pulgada (72–300 para uso típico) |
bbox_inches='tight' | Recorta el espacio en blanco alrededor de la figura |
transparent=True | Guarda con fondo transparente |
format='svg' | Escribe SVG vectorial en lugar de PNG ráster |
Problemas comunes
Valores que no suman 100. plt.pie() siempre normaliza los valores para que los sectores llenen el círculo completo. Si tus valores representan porcentajes que ya suman 100, está bien. Si representan recuentos brutos, también está bien — Matplotlib divide cada valor por el total. La etiqueta autopct siempre muestra la proporción, no el valor bruto.
Valores cero o negativos. Matplotlib omite silenciosamente los sectores con valor cero (no producen ningún sector visible). Los valores negativos generan un ValueError. Fíltralos antes de llamar a plt.pie().
Demasiados sectores. Los gráficos de pastel se vuelven ilegibles con más de 6–8 sectores. Para muchas categorías, considera un gráfico de barras en su lugar. Como alternativa, agrupa las categorías más pequeñas en un sector "Otros".
Superposición de etiquetas. Cuando los sectores son pequeños, las etiquetas colisionan. Las soluciones incluyen aumentar labeldistance, usar una leyenda en lugar de etiquetas en línea (establece labels=None y llama a plt.legend()), o usar un gráfico de donut con más espacio en el exterior.
Referencia rápida
| Parámetro | Tipo | Por defecto | Propósito |
|---|---|---|---|
x | sequence | — | Los valores de datos |
labels | list | None | Nombres de categorías |
colors | list | cycle | Colores de los sectores |
explode | tuple | None | Desplazamiento por sector desde el centro |
autopct | str / callable | None | Formato para las etiquetas de porcentaje |
pctdistance | float | 0.6 | Distancia de la etiqueta pct desde el centro |
labeldistance | float | 1.1 | Distancia de la etiqueta de categoría desde el centro |
startangle | float | 0 | Ángulo inicial en grados |
shadow | bool | False | Sombra paralela |
wedgeprops | dict | None | Propiedades pasadas a cada cuña (p. ej. width para donut) |
counterclock | bool | True | Dirección en que se dibujan los sectores |
Temas relacionados
- Gráficos de barras con Matplotlib — mejores que los gráficos de pastel cuando tienes muchas categorías o necesitas comparaciones precisas.
- Histogramas con Matplotlib — para visualizar la distribución de datos continuos.
- Etiquetas en Matplotlib — cómo añadir y dar estilo a las etiquetas de ejes, títulos y anotaciones.
- Subgráficos en Matplotlib — colocar varios gráficos en una misma figura.