Los gráficos de barras apiladas representan los valores que toman ciertos grupos dentro de otros grupos. Por ejemplo, considera que personas que viven en cinco ciudades diferentes (esto es, los grupos 'G1'
, 'G2'
, 'G3'
, 'G4'
y 'G5'
) respondieron Si
o No
a una pregunta y los resultados (el conteo de respuestas en cada ciudad) se guardaron en las variables valores1
y valores2
.
Estos datos se pueden representar en Python con la función bar
de matplotlib haciendo uso del argumento bottom
, que representa los valores del eje Y en los que dibujar la parte inferior de las barras, lo que nos permite apilar unas barras sobre otras.
import matplotlib.pyplot as plt
# Datos
grupos = ['G1', 'G2', 'G3', 'G4', 'G5']
valores1 = [12, 19, 14, 27, 16]
valores2 = [21, 30, 15, 17, 20]
fig, ax = plt.subplots()
# Gráfico de barras apiladas
ax.bar(grupos, valores1)
ax.bar(grupos, valores2, bottom = valores1)
# plt.show()
Gráfico de barras apiladas con tres subgrupos
Si tienes que apilar más de dos barras tendrás que pasar los valores agregados de los datos anteriores a bottom
, como en el ejemplo siguiente.
import matplotlib.pyplot as plt
import numpy as np
# Datos
grupos = ['G1', 'G2', 'G3', 'G4', 'G5']
valores1 = [12, 19, 14, 27, 16]
valores2 = [21, 30, 15, 17, 20]
values3 = [15, 23, 12, 11, 15]
fig, ax = plt.subplots()
# Gráfico de barras apiladas
ax.bar(grupos, valores1)
ax.bar(grupos, valores2, bottom = valores1)
ax.bar(grupos, values3, bottom = np.add(valores1, valores2))
# plt.show()
Generalización para varios subgrupos
Sin embargo, si no quieres apilar los valores manualmente puedes unir los valores en un array de numpy y luego utilizar el siguiente bucle for
:
import matplotlib.pyplot as plt
import numpy as np
# Datos
grupos = ['G1', 'G2', 'G3', 'G4', 'G5']
values = np.array([[12, 19, 14, 27, 16],
[21, 30, 15, 17, 20],
[15, 23, 12, 11, 15],
[2, 5, 1, 6, 8]])
fig, ax = plt.subplots()
# Gráfico de barras apiladas con un bucle
for i in range(values.shape[0]):
ax.bar(grupos, values[i], bottom = np.sum(values[:i], axis = 0))
# plt.show()
Grosor de las barras
El argumento width
controla el grosor de las barras. El valor por defecto es 0.8.
import matplotlib.pyplot as plt
# Datos
grupos = ['G1', 'G2', 'G3', 'G4', 'G5']
valores1 = [12, 19, 14, 27, 16]
valores2 = [21, 30, 15, 17, 20]
grosor = 0.25
fig, ax = plt.subplots()
# Gráfico de barras apiladas
ax.bar(grupos, valores1, width = grosor)
ax.bar(grupos, valores2, width = grosor, bottom = valores1)
# plt.show()
Barras de error
Puedes agregar barras de error a las barras apiladas con el argumento yerr
. Tendrás que pasar la desviación típica para cada subgrupo. Ten en cuenta que puedes personalizar el color de las barras de error con ecolor
y el tamaño de las barras horizontales con capsize
.
import matplotlib.pyplot as plt
# Datos
grupos = ['G1', 'G2', 'G3', 'G4', 'G5']
valores1 = [12, 19, 14, 27, 16]
valores2 = [21, 30, 15, 17, 20]
valores1_std = [2, 1, 3, 0.5, 2]
valores2_std = [1, 4, 0.25, 0.75, 1]
fig, ax = plt.subplots()
# Gráfico de barras apiladas
ax.bar(grupos, valores1, yerr = valores1_std, ecolor = 'red')
ax.bar(grupos, valores2, yerr = valores2_std, ecolor = 'green', bottom = valores1)
# plt.show()
El color de las barras de cada subgrupo se puede personalizar con el argumento color
. Ten en cuenta que también puedes modificar la transparencia de los colores con alpha
.
import matplotlib.pyplot as plt
# Datos
grupos = ['G1', 'G2', 'G3', 'G4', 'G5']
valores1 = [12, 19, 14, 27, 16]
valores2 = [21, 30, 15, 17, 20]
fig, ax = plt.subplots()
# Gráfico de barras apiladas
ax.bar(grupos, valores1, color = "#024b7a", alpha = 0.5)
ax.bar(grupos, valores2, bottom = valores1, color = "#44a5c2", alpha = 0.5)
# plt.show()
Además, puedes modificar el color y grosor del borde de las barras con edgecolor
y linewidth
, respectivamente.
import matplotlib.pyplot as plt
# Datos
grupos = ['G1', 'G2', 'G3', 'G4', 'G5']
valores1 = [12, 19, 14, 27, 16]
valores2 = [21, 30, 15, 17, 20]
fig, ax = plt.subplots()
# Gráfico de barras apiladas
ax.bar(grupos, valores1, color = "#44a5c2",
edgecolor = "black", linewidth = 2)
ax.bar(grupos, valores2, bottom = valores1, color = "#ffae49",
edgecolor = "black", linewidth = 2)
# plt.show()
Puedes establecer una etiqueta para cada subgrupo con el argumento label
. Una vez agregadas las etiquetas podrás llamar a la función legend
para agregar una leyenda al gráfico, como en el ejemplo siguiente.
import matplotlib.pyplot as plt
# Datos
grupos = ['G1', 'G2', 'G3', 'G4', 'G5']
valores1 = [12, 19, 14, 27, 16]
valores2 = [21, 30, 15, 17, 20]
fig, ax = plt.subplots()
# Gráfico de barras apiladas
ax.bar(grupos, valores1, label = "Si")
ax.bar(grupos, valores2, bottom = valores1, label = "No")
ax.legend(loc = 'upper right')
ax.set_ylabel('Número de respuestas')
# plt.show()
Puedes mostrar los valores numéricos para cada barra apilada con la función text
de matplotlib. Para ello puedes utilizar un bucle for
como el siguiente:
import matplotlib.pyplot as plt
# Datos
grupos = ['G1', 'G2', 'G3', 'G4', 'G5']
valores1 = [12, 19, 14, 27, 16]
valores2 = [21, 30, 15, 17, 20]
fig, ax = plt.subplots()
# Gráfico de barras apiladas
ax.bar(grupos, valores1, label = "Si")
ax.bar(grupos, valores2, bottom = valores1, label = "No")
# Etiquetas
for bar in ax.patches:
ax.text(bar.get_x() + bar.get_width() / 2,
bar.get_height() / 2 + bar.get_y(),
round(bar.get_height()), ha = 'center',
color = 'w', weight = 'bold', size = 10)
ax.legend(loc = 'upper right')
ax.set_ylabel('Número de respuestas')
# plt.show()
Valor total de cada grupo
Alternativamente, puedes agregar etiquetas con los valores del total para cada grupo o barra. Para ello, tendrás que sumar los valores de cada grupo y luego utilizar un bucle for
que recorra cada valor.
import matplotlib.pyplot as plt
import numpy as np
# Datos
grupos = ['G1', 'G2', 'G3', 'G4', 'G5']
valores1 = [12, 19, 14, 27, 16]
valores2 = [21, 30, 15, 17, 20]
fig, ax = plt.subplots()
# Gráfico de barras apiladas
ax.bar(grupos, valores1, label = "Si")
ax.bar(grupos, valores2, bottom = valores1, label = "No")
# Suma de valores
total_values = np.add(valores1, valores2)
# Etiquetas con el total
for i, total in enumerate(total_values):
ax.text(i, total + 0.5, round(total),
ha = 'center', weight = 'bold', color = 'black')
ax.legend(loc = 'upper right')
ax.set_ylabel('Número de respuestas')
plt.show()
También te puede interesar