• Saltar al contenido principal
  • Skip to secondary menu
  • Saltar a la barra lateral principal
  • Saltar al pie de página
  • Inicio
  • Secciones
    • Ciencia de datos
    • Criptografía
    • Herramientas
    • Machine Learning
    • Noticias
    • Opinión
    • Productividad
    • Programación
      • JavaScript
      • Julia
      • Matlab
      • Python
      • R
  • Programación
    • JavaScript
    • Julia
    • Matlab
    • Python
    • R
  • Laboratorio
    • Estadística
      • Calculadora del Tamaño Muestral en Encuestas
      • Calculadora de estadísticos descriptivos
      • Test de normalidad
      • Calculadora de contrastes de hipotesis
      • Calculadora de tamano del efecto
      • Simulador de Regresión Lineal con Ruido
      • Visualizador de PCA
      • Visualizador de Series Temporales
      • Simulador de Regresión Logística
      • Simulador de K-Means
      • Simulador de DBSCAN
      • Detector de la Ley de Benford
    • Probabilidad
      • Calculadora de Probabilidad de Distribuciones
      • Calculadora de Probabilidades de Lotería
      • Simulador del Problema de Monty Hall
      • Simulador de la Estrategia Martingala
    • Finanzas
      • Calculadora de Préstamos e Hipotecas
      • Conversor TIN ↔ TAE
      • Calculadora DCA con ajuste por inflación
      • Calculadora XIRR con Flujos Irregulares
      • Simulador FIRE (Financial Independence, Retire Early)
    • Riesgo
      • Constructor de Scorecards de Crédito
      • Aplicar Scorecard de Crédito
    • Herramientas
      • Formateador / Minificador de JSON
      • Conversor CSV ↔ JSON
      • Comparador y Formateador de Texto y JSON
      • Formateador y Tester de Expresiones Regulares
      • Inspector de JWT
      • Generador y verificador de hashes
      • Codificador / Decodificador Base64 y URL
      • Conversor de bases numericas
      • Conversor de Timestamp Unix
      • Conversor de colores
      • Generador de UUIDs
    • Juegos
      • Tres en Raya
      • Nim con Q-Learning
    • Más
      • Método D’Hondt
      • Generador de Contraseñas Seguras
  • Noticias
  • Boletín
  • Contacto
  • Tienda
    • Libros
    • Equipamiento de oficina
    • Equipamiento en movilidad

Analytics Lane

Ciencia e ingeniería de datos aplicada

  • Ciencia de datos
  • Machine Learning
  • IA Generativa
  • Python
  • Pandas
  • NumPy
  • R
  • Excel

Cómo comparar datos con barras en Matplotlib: agrupadas, apiladas y porcentuales

mayo 12, 2026 Por Daniel Rodríguez Deja un comentario
Tiempo de lectura: 9 minutos

Tienes los datos de ventas de tres productos en dos años distintos y quieres saber cuál creció más. Podrías hacer dos gráficos separados… pero tu cerebro tardaría el doble en extraer conclusiones. La solución es un gráfico de barras comparativo, y en esta entrada verás exactamente cómo construirlo en Python con Matplotlib, paso a paso.

En concreto, veremos tres técnicas fundamentales:

  • Barras agrupadas (grouped bar charts): para comparar valores directamente entre grupos.
  • Barras apiladas (stacked bar charts): para ver la composición del total.
  • Barras porcentuales: para analizar proporciones y eliminar el efecto del tamaño absoluto.

Al final del artículo encontrarás una tabla resumen para saber cuándo usar cada una.

Tabla de contenidos

  • 1 Recordatorio rápido: el gráfico de barras básico
  • 2 Gráficos de barras agrupadas (Grouped Bar Charts)
    • 2.1 El concepto clave: posicionamiento numérico
    • 2.2 Implementación con dos series
    • 2.3 Escalando a tres o más series
  • 3 Gráficos de barras apiladas (Stacked Bar Charts)
    • 3.1 Implementación básica
    • 3.2 Apilando tres o más series
  • 4 Comparación porcentual (barras normalizadas)
    • 4.1 Implementación paso a paso
  • 5 Mejoras estéticas para gráficos más legibles
    • 5.1 Estilo base
    • 5.2 Cuadrícula horizontal
    • 5.3 Rotación de etiquetas
    • 5.4 Colores personalizados
    • 5.5 Añadir etiquetas de valor sobre las barras
  • 6 Errores comunes y cómo evitarlos
  • 7 Caso práctico completo
  • 8 Resumen: ¿cuándo usar cada tipo de gráfico?
  • 9 Conclusiones

Recordatorio rápido: el gráfico de barras básico

Antes de entrar en comparaciones, repasemos la forma más simple de crear un gráfico de barras en Matplotlib:

import matplotlib.pyplot as plt

categorias = ['A', 'B', 'C']
valores = [10, 15, 7]

plt.bar(categorias, valores)
plt.title("Gráfico de barras básico")
plt.ylabel("Valores")
plt.show()

Este gráfico funciona perfectamente cuando tienes una sola variable y categorías independientes. Pero en cuanto quieres añadir una segunda serie de datos —por ejemplo, los mismos productos en un año diferente— este enfoque se queda corto. No puedes superponer dos llamadas a plt.bar() sin que las barras se solapen o se oculten entre sí.

Nuevo test de normalidad interactivo en el laboratorio de Analytics Lane
En Analytics Lane
Nuevo test de normalidad interactivo en el laboratorio de Analytics Lane

Es justo ahí donde necesitas las técnicas que vamos a ver a continuación.

Gráficos de barras agrupadas (Grouped Bar Charts)

Las barras agrupadas son la elección correcta cuando quieres comparar directamente dos o más series dentro de la misma categoría. Por ejemplo:

  • Ventas de varios productos en distintos años.
  • Rendimiento de algoritmos en distintos conjuntos de datos.
  • Resultados de encuestas segmentadas por edad o región.

Publicidad


El concepto clave: posicionamiento numérico

Matplotlib no trabaja internamente con categorías de texto como 'Producto A' o 'Q1'. En realidad, todo se basa en posiciones numéricas en el eje X. Esto nos da el control total para desplazar las barras horizontalmente y evitar que se solapen.

El truco consiste en seguir los siguientes tres pasos:

  1. Convertir las categorías en números con np.arange.
  2. Definir el ancho de cada barra.
  3. Desplazar cada grupo de barras hacia la izquierda o la derecha.

Implementación con dos series

Empecemos con el caso más habitual: comparar dos años de ventas para tres productos.

import numpy as np
import matplotlib.pyplot as plt

categorias = ['Producto A', 'Producto B', 'Producto C']
ventas_2023 = [10, 15, 20]
ventas_2024 = [12, 18, 25]

# Paso 1: convertir categorías en posiciones numéricas
x = np.arange(len(categorias))  # → [0, 1, 2]

# Paso 2: definir el ancho de cada barra
width = 0.35

# Paso 3: dibujar las barras desplazadas
plt.bar(x - width/2, ventas_2023, width, label='2023')
plt.bar(x + width/2, ventas_2024, width, label='2024')

# Sustituir los números del eje X por las etiquetas reales
plt.xticks(x, categorias)
plt.ylabel('Ventas')
plt.title('Comparación de ventas por producto')
plt.legend()
plt.show()

Vamos a entender exactamente qué hace cada parte de este código:

  • x = np.arange(len(categorias)): Genera el array [0, 1, 2]. Cada número representa la posición central de un grupo de barras en el eje X.
  • width = 0.35: Controla el ancho de cada barra individual. Un valor entre 0.25 y 0.4 suele funcionar bien. Si lo haces demasiado grande las barras se solaparán; si es demasiado pequeño, el gráfico quedará lleno de espacio vacío.
  • x - width/2 y x + width/2: Aquí está la clave. En lugar de dibujar ambas barras en la posición x, desplazamos la primera hacia la izquierda (-width/2) y la segunda hacia la derecha (+width/2). El resultado es que las dos barras quedan centradas alrededor de cada posición, sin solaparse.
  • plt.xticks(x, categorias): Como el eje X contiene números (0, 1, 2), esta línea los sustituye por las etiquetas de texto originales. Sin esto, el gráfico mostraría 0, 1, 2 en lugar de los nombres de los productos.

Escalando a tres o más series

En análisis real es frecuente trabajar con más de dos grupos. Supongamos ahora tres años:

ventas_2022 = [8, 12, 18]
ventas_2023 = [10, 15, 20]
ventas_2024 = [12, 18, 25]

x = np.arange(len(categorias))
width = 0.25  # Reducimos el ancho para que quepan tres barras

plt.bar(x - width,     ventas_2022, width, label='2022')
plt.bar(x,             ventas_2023, width, label='2023')
plt.bar(x + width,     ventas_2024, width, label='2024')

plt.xticks(x, categorias)
plt.legend()
plt.title("Comparación multianual")
plt.show()

Observa que al añadir una tercera barra hemos tenido que reducir el width a 0.25 para que las tres quepan. La barra central permanece en x, y las otras dos se desplazan simétricamente.

Advertencia: a partir de 4 o 5 grupos, las barras agrupadas se vuelven difíciles de leer. Si tienes muchas series, considera usar líneas temporales, heatmaps o dividir el análisis en varios gráficos. Más información no siempre es mejor visualización.

Publicidad


Gráficos de barras apiladas (Stacked Bar Charts)

Las barras apiladas son ideales cuando lo que te importa no es comparar los valores entre sí, sino ver cómo varias partes componen un total. Por ejemplo:

  • Desglose de ingresos por línea de producto.
  • Tiempo invertido en distintas tareas durante la semana.
  • Contribución de cada departamento al presupuesto total.

Implementación básica

La clave aquí es el parámetro bottom. Este parámetro le indica a Matplotlib desde qué altura debe empezar a dibujar la siguiente barra. Sin él, todas las barras empezarían desde cero y se solaparían.

categorias = ['Producto A', 'Producto B', 'Producto C']
ventas_2023 = [10, 15, 20]
ventas_2024 = [12, 18, 25]

plt.bar(categorias, ventas_2023, label='2023')
plt.bar(categorias, ventas_2024, bottom=ventas_2023, label='2024')

plt.legend()
plt.title("Barras apiladas: ventas acumuladas")
plt.ylabel("Ventas totales")
plt.show()

En este caso, la barra de 2023 forma la base y la de 2024 se apila encima. El alto total de cada barra representa la suma de ambos años, lo que permite ver rápidamente qué producto tiene mayor volumen acumulado.

Apilando tres o más series

Para apilar tres series, simplemente acumulamos los bottom de forma progresiva:

ventas_2022 = np.array([8, 12, 18])
ventas_2023 = np.array([10, 15, 20])
ventas_2024 = np.array([12, 18, 25])

plt.bar(categorias, ventas_2022, label='2022')
plt.bar(categorias, ventas_2023, bottom=ventas_2022, label='2023')
plt.bar(categorias, ventas_2024, bottom=ventas_2022 + ventas_2023, label='2024')

plt.legend()
plt.title("Barras apiladas con tres series")
plt.show()

Es importante usar np.array en lugar de listas de Python para poder sumar los arrays directamente con el operador +.

Error frecuente: usar barras apiladas cuando en realidad quieres comparar. Si tu pregunta es “¿cuánto vendió el Producto A en 2023 frente a 2024?”, las barras apiladas no te ayudan, porque la segunda barra no empieza en cero. Para comparación directa, usa siempre barras agrupadas.

Publicidad


Comparación porcentual (barras normalizadas)

A veces los valores absolutos distorsionan la imagen. Imagina que el Producto A vende 100 unidades y el Producto B vende 10.000. Si los representas juntos con barras apiladas, la contribución de A quedará casi invisible aunque sea importante en términos relativos.

La normalización soluciona esto: convierte los valores a porcentaje sobre el total, de forma que todas las barras alcanzan exactamente el 100 %. Esto permite comparar la estructura interna de cada categoría independientemente de su tamaño.

Implementación paso a paso

import numpy as np
import matplotlib.pyplot as plt

categorias = ['Producto A', 'Producto B', 'Producto C']
ventas_2023 = np.array([10, 15, 20])
ventas_2024 = np.array([12, 18, 25])

# Calcular el total por producto
total = ventas_2023 + ventas_2024

# Convertir a porcentaje
ventas_2023_pct = ventas_2023 / total * 100
ventas_2024_pct = ventas_2024 / total * 100

# Dibujar el gráfico apilado porcentual
plt.bar(categorias, ventas_2023_pct, label='2023')
plt.bar(categorias, ventas_2024_pct, bottom=ventas_2023_pct, label='2024')

plt.ylabel('%')
plt.ylim(0, 100)
plt.title("Distribución porcentual de ventas por producto")
plt.legend()
plt.show()

Ahora todas las barras llegan al 100 % y puedes ver fácilmente si el peso relativo de cada año ha cambiado entre productos, independientemente de cuántas unidades vendieron.

Mejoras estéticas para gráficos más legibles

Un gráfico correcto técnicamente puede ser difícil de interpretar si no cuida la presentación. Estas son las mejoras más efectivas:

Publicidad


Estilo base

plt.style.use('seaborn-v0_8')

Este estilo añade un fondo limpio y colores predefinidos más suaves que los del estilo por defecto de Matplotlib.

Cuadrícula horizontal

plt.grid(axis='y', linestyle='--', alpha=0.7)

Una cuadrícula en el eje Y ayuda al ojo a estimar valores sin sobrecargar el gráfico. El parámetro alpha=0.7 la hace semitransparente para que no compita con los datos.

Rotación de etiquetas

plt.xticks(rotation=45, ha='right')

Cuando los nombres de categoría son largos, rotarlos 45 grados evita que se solapen. El ha='right' (horizontal alignment) asegura que el texto quede bien alineado bajo su barra.

Publicidad


Colores personalizados

colores = ['steelblue', 'darkorange', 'seagreen']
plt.bar(x, ventas_2023, color=colores[0])
plt.bar(x, ventas_2024, color=colores[1])

Elegir colores con buen contraste mejora la legibilidad, especialmente para lectores con daltonismo. Paletas como tab10 o Set2 de Matplotlib son buenas opciones accesibles.

Añadir etiquetas de valor sobre las barras

for i, v in enumerate(ventas_2023):
    plt.text(i - width/2, v + 0.3, str(v), ha='center', fontsize=9)

Mostrar el valor exacto encima de cada barra elimina la necesidad de que el lector estime mirando el eje, lo que hace el gráfico más autónomo.

Errores comunes y cómo evitarlos

Antes de ver el ejemplo final, conviene revisar los errores más frecuentes al construir este tipo de gráficos:

  • No usar np.arange para las posiciones: Si intentas pasar listas de texto directamente a plt.bar() con desplazamientos, Matplotlib no sabrá cómo calcular las posiciones y las barras se solaparán o darán error. Siempre convierte a posiciones numéricas primero.
  • Ancho de barra (width) mal ajustado: Con dos series y width=0.5, las barras se tocan o se superponen. Con width=0.1, quedan demasiado delgadas y el gráfico parece vacío. Ajusta el ancho en función del número de series: divide el espacio disponible (~0.8 unidades) entre el número de barras por grupo.
  • Demasiadas series en el mismo gráfico: A partir de 4–5 grupos distintos, las barras agrupadas se vuelven ilegibles. En ese caso es mejor usar líneas, pequeños múltiplos (small multiples) o un heatmap.
  • Mezclar barras apiladas y comparación directa: Recuerda que en las barras apiladas la segunda barra no empieza en cero, lo que hace imposible comparar su altura con la primera. Si necesitas comparar magnitudes, usa siempre barras agrupadas.
  • Olvidar normalizar en análisis porcentual: Si tus categorías tienen tamaños muy distintos y quieres comparar proporciones, trabajar con valores absolutos puede llevar a conclusiones erróneas. Normaliza siempre antes de representar proporciones.

Publicidad


Caso práctico completo

Pongamos todo junto en un ejemplo realista: comparar las ventas trimestrales de dos empresas con un gráfico bien presentado.

import numpy as np
import matplotlib.pyplot as plt

plt.style.use('seaborn-v0_8')

categorias = ['Q1', 'Q2', 'Q3', 'Q4']
empresa_a = [10, 14, 18, 20]
empresa_b = [12, 16, 22, 24]

x = np.arange(len(categorias))
width = 0.35

fig, ax = plt.subplots(figsize=(9, 5))

bars_a = ax.bar(x - width/2, empresa_a, width, label='Empresa A', color='steelblue')
bars_b = ax.bar(x + width/2, empresa_b, width, label='Empresa B', color='darkorange')

# Etiquetas de valor
for bar in bars_a:
    ax.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 0.3,
            str(int(bar.get_height())), ha='center', va='bottom', fontsize=9)
for bar in bars_b:
    ax.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 0.3,
            str(int(bar.get_height())), ha='center', va='bottom', fontsize=9)

ax.set_xticks(x)
ax.set_xticklabels(categorias)
ax.set_ylabel('Ventas (miles €)')
ax.set_title('Comparación trimestral de ventas: Empresa A vs Empresa B')
ax.legend()
ax.grid(axis='y', linestyle='--', alpha=0.6)

plt.tight_layout()
plt.show()

El uso de fig, ax = plt.subplots() es la forma recomendada de trabajar en Matplotlib cuando se quiere un control más preciso del gráfico. El objeto ax expone los mismos métodos que plt, pero es más explícito y facilita la creación de múltiples subgráficos en el futuro.

Resumen: ¿cuándo usar cada tipo de gráfico?

TipoÚsalo cuando quieras…Limitación principal
Barras agrupadasComparar valores directamente entre gruposDifícil de leer con más de 4 series
Barras apiladasVer la composición y el total acumuladoNo permite comparar partes entre categorías
Barras porcentualesAnalizar proporciones eliminando el tamaño absolutoPierdes información sobre los valores reales

Conclusiones

Los gráficos de barras comparativos son una de las herramientas más versátiles del análisis de datos. Con Matplotlib puedes construir desde una comparación directa entre dos grupos hasta un análisis porcentual multiserie, siempre que entiendas bien el mecanismo de posicionamiento y elijas el tipo de gráfico adecuado para tu pregunta.

La regla de oro es simple: antes de escribir el código, pregúntate qué quieres que el lector vea. ¿Una diferencia? Usa barras agrupadas. ¿Una composición? Apílalas. ¿Una proporción? Normaliza. El tipo de gráfico es siempre una consecuencia de la pregunta analítica, nunca al revés.

¿Te ha parecido de utilidad el contenido?

¡Puntúalo entre una y cinco estrellas!

Puntuación promedio 0 / 5. Votos emitidos: 0

Ya que has encontrado útil este contenido...

¡Síguenos en redes sociales!

¡Siento que este contenido no te haya sido útil!

¡Déjame mejorar este contenido!

Dime, ¿cómo puedo mejorar este contenido?

Publicidad


Publicaciones relacionadas

  • Nuevo test de normalidad interactivo en el laboratorio de Analytics Lane
  • Nuevo conversor de timestamp Unix en el laboratorio de Analytics Lane
  • Calculadora de Contrastes de Hipótesis: interpreta correctamente el p-valor y toma decisiones estadísticas con confianza
  • Calculadora de Tamaño del Efecto: la herramienta clave para entender cuánto importa realmente una diferencia
  • Simulador de DBSCAN: descubre cómo encontrar clusters reales (y ruido) sin fijar K
  • Conversor de Colores: convierte, compara y valida cualquier color en tiempo real
  • Analytics Lane lanza su Generador de UUIDs: identificadores únicos, seguros y listos para producción en segundos
  • 1200 publicaciones en Analytics Lane
  • Analytics Lane lanza su Conversor TIN ↔ TAE: la herramienta definitiva para entender el coste real de depósitos, préstamos e hipotecas

Publicado en: Python Etiquetado como: Matplotlib

Interacciones con los lectores

Deja una respuesta Cancelar la respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

I accept the Terms and Conditions and the Privacy Policy

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

Barra lateral principal

Suscríbete a nuestro boletín

Suscríbete al boletín semanal para estar al día de todas las publicaciones.

Política de Privacidad

Analytics Lane en redes sociales

  • Amazon
  • Bluesky
  • Facebook
  • GitHub
  • Instagram
  • Mastodon
  • Pinterest
  • RSS
  • Telegram
  • Tumblr
  • Twitter
  • YouTube

Publicidad

Entradas recientes

Cómo comparar datos con barras en Matplotlib: agrupadas, apiladas y porcentuales

mayo 12, 2026 Por Daniel Rodríguez

Costes hundidos en ciencia de datos: cuándo mantener un modelo y cuándo migrar

mayo 7, 2026 Por Daniel Rodríguez

WOE e IV: La Base Matemática del Credit Scoring

mayo 5, 2026 Por Daniel Rodríguez

Publicidad

Es tendencia

  • Gráficos de barras en Matplotlib publicado el julio 5, 2022 | en Python
  • Método del codo (Elbow method) para seleccionar el número óptimo de clústeres en K-means publicado el junio 9, 2023 | en Ciencia de datos
  • Media, mediana y moda: Descubre cómo interpretar las medidas de tendencia central con ejemplos claros y sin complicaciones publicado el mayo 16, 2025 | en Ciencia de datos
  • Creación de gráficos de barras y gráficos de columnas con Seaborn publicado el julio 18, 2023 | en Python
  • Exactitud, precisión, recall… qué mide realmente cada métrica (y qué no) publicado el marzo 3, 2026 | en Ciencia de datos

Publicidad

Lo mejor valorado

4.9 (24)

Seleccionar filas y columnas en Pandas con iloc y loc

4.6 (16)

Archivos JSON con Python: lectura y escritura

4.4 (14)

Ordenación de diccionarios en Python mediante clave o valor

4.7 (13)

Operaciones de filtrado de DataFrame con Pandas en base a los valores de las columnas

4.9 (11)

Pandas: Cambiar los tipos de datos en los DataFrames

Comentarios recientes

  • M. Pilar en Cómo eliminar las noticias en Windows 11 y recuperar tu concentración
  • Daniel Rodríguez en Probabilidad básica: cómo entender el azar en nuestra vida diaria
  • Pepe en Probabilidad básica: cómo entender el azar en nuestra vida diaria
  • CARLOS ARETURO BELLO CACERES en Justicio: La herramienta gratuita de IA para consultas legales
  • Piera en Ecuaciones multilínea en Markdown

Publicidad


Footer

Analytics Lane

  • Acerca de Analytics Lane
  • Boletín de noticias
  • Contacto
  • Libros
  • Lo más popular
  • Noticias
  • Tienda
  • Tiendas afiliadas

Secciones

  • Ciencia de datos
  • Criptografía
  • Herramientas
  • Machine Learning
  • Opinión
  • Productividad
  • Programación
  • Reseñas

Sobre de Analytics Lane

En Analytics Lane tratamos de explicar los principales conceptos de la ciencia e ingeniería de datos con un enfoque práctico. Los principales temas tratados son ciencia de datos, ingeniería de datos, inteligencia artificial, machine learning, deep learning y criptografía. Además, también se habla de los principales lenguajes de programación y herramientas utilizadas por los científicos e ingenieros de datos.

Copyright © 2018-2026 Analytics Lane ·Términos y condiciones ·Política de Cookies ·Política de Privacidad ·Herramientas de privacidad ·Contacto