Stacked bar charts represent the values which take different groups within other groups. For instance, consider that people living in five different cities (e.g., the groups, named 'G1', 'G2', 'G3', 'G4' and 'G5') answered Yes or No to one question and the results (the count of Yes and No for each city) were stored into values1 and values2 variables.
This data can be represented in Python with the bar function from matplotlib making use of the bottom argument, which represents the Y coordinates used to draw the bottom of the bars, so you can stack several bars.
import matplotlib.pyplot as plt
# Data
groups = ['G1', 'G2', 'G3', 'G4', 'G5']
values1 = [12, 19, 14, 27, 16]
values2 = [21, 30, 15, 17, 20]
fig, ax = plt.subplots()
# Stacked bar chart
ax.bar(groups, values1)
ax.bar(groups, values2, bottom = values1)
# plt.show()

Stacked bar plot with three subgroups
If you have to stack more than two subgroups you will need to pass the added values of the previous data to bottom, as in the example below.
import matplotlib.pyplot as plt
import numpy as np
# Data
groups = ['G1', 'G2', 'G3', 'G4', 'G5']
values1 = [12, 19, 14, 27, 16]
values2 = [21, 30, 15, 17, 20]
values3 = [15, 23, 12, 11, 15]
fig, ax = plt.subplots()
# Stacked bar chart
ax.bar(groups, values1)
ax.bar(groups, values2, bottom = values1)
ax.bar(groups, values3, bottom = np.add(values1, values2))
# plt.show()

Generalization with multiple subgroups
However, if you don’t want to stack the values manually of the stacked bar graph you can join the values into a numpy array and then use the following for loop:
import matplotlib.pyplot as plt
import numpy as np
# Data
groups = ['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()
# Stacked bar chart with loop
for i in range(values.shape[0]):
ax.bar(groups, values[i], bottom = np.sum(values[:i], axis = 0))
# plt.show()

Bars width
The width argument controls the width of the bars. The default value is 0.8.
import matplotlib.pyplot as plt
# Data
groups = ['G1', 'G2', 'G3', 'G4', 'G5']
values1 = [12, 19, 14, 27, 16]
values2 = [21, 30, 15, 17, 20]
width = 0.25
fig, ax = plt.subplots()
# Stacked bar chart
ax.bar(groups, values1, width = width)
ax.bar(groups, values2, width = width, bottom = values1)
# plt.show()

Error bars
You can add error bars to the stacked bar plot with the yerr argument. You will need to input the standard deviation for each subgroup. Note that you can customize the color of the error bars with ecolor and the size of the caps with capsize.
import matplotlib.pyplot as plt
# Data
groups = ['G1', 'G2', 'G3', 'G4', 'G5']
values1 = [12, 19, 14, 27, 16]
values2 = [21, 30, 15, 17, 20]
values1_std = [2, 1, 3, 0.5, 2]
values2_std = [1, 4, 0.25, 0.75, 1]
fig, ax = plt.subplots()
# Stacked bar chart
ax.bar(groups, values1, yerr = values1_std, ecolor = 'red')
ax.bar(groups, values2, yerr = values2_std, ecolor = 'green', bottom = values1)
# plt.show()

The color of the bars for each subgroup can be customized through the color argument. Note that you can also customize the transparency of the colors with alpha.

import matplotlib.pyplot as plt
# Data
groups = ['G1', 'G2', 'G3', 'G4', 'G5']
values1 = [12, 19, 14, 27, 16]
values2 = [21, 30, 15, 17, 20]
fig, ax = plt.subplots()
# Stacked bar chart
ax.bar(groups, values1, color = "#024b7a", alpha = 0.5)
ax.bar(groups, values2, bottom = values1, color = "#44a5c2", alpha = 0.5)
# plt.show()
In addition, you can modify the border color and width of the bars with edgecolor and linewidth, respectively.

import matplotlib.pyplot as plt
# Data
groups = ['G1', 'G2', 'G3', 'G4', 'G5']
values1 = [12, 19, 14, 27, 16]
values2 = [21, 30, 15, 17, 20]
fig, ax = plt.subplots()
# Stacked bar chart
ax.bar(groups, values1, color = "#44a5c2",
edgecolor = "black", linewidth = 2)
ax.bar(groups, values2, bottom = values1, color = "#ffae49",
edgecolor = "black", linewidth = 2)
# plt.show()
You can set a label for each subgroup with the label argument. Then, you can make use of the legend function to add the legend to the plot, as in the example below.
import matplotlib.pyplot as plt
# Data
groups = ['G1', 'G2', 'G3', 'G4', 'G5']
values1 = [12, 19, 14, 27, 16]
values2 = [21, 30, 15, 17, 20]
fig, ax = plt.subplots()
# Stacked bar chart
ax.bar(groups, values1, label = "Yes")
ax.bar(groups, values2, bottom = values1, label = "No")
ax.legend()
ax.set_ylabel('Number of answers')
# plt.show()

You can display the numerical values for each bar within the stack with the text function from matplotlib. In order to add them, you can use a for loop like the following:

import matplotlib.pyplot as plt
# Data
groups = ['G1', 'G2', 'G3', 'G4', 'G5']
values1 = [12, 19, 14, 27, 16]
values2 = [21, 30, 15, 17, 20]
fig, ax = plt.subplots()
# Stacked bar chart
ax.bar(groups, values1, label = "Yes")
ax.bar(groups, values2, bottom = values1, label = "No")
# Labels
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()
ax.set_ylabel('Number of answers')
# plt.show()
Total value labels
Alternatively, you can add labels representing the total value for each group or bar. For this purpose, you will need to add the values and then use a for loop to loop through each label, as in the following example.

import matplotlib.pyplot as plt
import numpy as np
# Data
groups = ['G1', 'G2', 'G3', 'G4', 'G5']
values1 = [12, 19, 14, 27, 16]
values2 = [21, 30, 15, 17, 20]
fig, ax = plt.subplots()
# Stacked bar chart
ax.bar(groups, values1, label = "Yes")
ax.bar(groups, values2, bottom = values1, label = "No")
# Sum of values
total_values = np.add(values1, values2)
# Total values labels
for i, total in enumerate(total_values):
ax.text(i, total + 0.5, round(total),
ha = 'center', weight = 'bold', color = 'black')
ax.legend()
ax.set_ylabel('Number of answers')
plt.show()
See also