W3docs

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 matplotlib

Cada ejemplo de este capítulo comienza con esta importación:

import matplotlib.pyplot as plt

plt 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ámetroPropósito
valuesDatos numéricos; Matplotlib los convierte en proporciones
labelsNombres de categorías dibujados junto a cada sector
autopctCadena 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 es 1.1 (justo fuera del sector).
  • pctdistance — distancia de la etiqueta de porcentaje autopct desde el centro. El valor por defecto es 0.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ónEfecto
dpi=150Resolución en puntos por pulgada (72–300 para uso típico)
bbox_inches='tight'Recorta el espacio en blanco alrededor de la figura
transparent=TrueGuarda 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ámetroTipoPor defectoPropósito
xsequenceLos valores de datos
labelslistNoneNombres de categorías
colorslistcycleColores de los sectores
explodetupleNoneDesplazamiento por sector desde el centro
autopctstr / callableNoneFormato para las etiquetas de porcentaje
pctdistancefloat0.6Distancia de la etiqueta pct desde el centro
labeldistancefloat1.1Distancia de la etiqueta de categoría desde el centro
startanglefloat0Ángulo inicial en grados
shadowboolFalseSombra paralela
wedgepropsdictNonePropiedades pasadas a cada cuña (p. ej. width para donut)
counterclockboolTrueDirección en que se dibujan los sectores

Temas relacionados

Was this page helpful?