Skip to content

#172: Combine Multiple Plots in Matplotlib

Matplotlib allows us to draw our annotations on top of a plot. Today we look what happens if we draw a plot on top of another plot.

Line plots work well

We can draw one line plot on top of another without any problems:

1
2
3
4
5
6
7
x = [1, 2, 3, 4]
y_a = [0, 6, 1, 2]
y_b = [1, 2, 4, 5]
fig, ax = plt.subplots()
ax.plot(x, y_a, label='first')
ax.plot(x, y_b, label='second')
ax.legend()

This gives us a figure with a line in red for the first and a line in green for the second plot:

Two lines (red, green) share the same figure

By specifying the parameter legend for each plot, we can have a legend on the figure.

Bar charts overlay each other

We can combine two bar charts and put them on the same axes:

1
2
3
4
5
6
7
8
month = ['January', 'February', 'March', 'April', 'May', 'June']
temp_average_day = [3.4, 5.2, 10.3, 14.5, 18.6, 22.5]
temp_average_night = [-2.9, -2.8, 0.3, 3.4, 7.6, 11.3]

fig, ax = plt.subplots()
ax.bar(month, temp_average_day, label='day')
ax.bar(month, temp_average_night, label='night')
ax.legend()

We are lucky and the data we have for night and day temperature averages can be combined without any problems:

The orange night average temperature does not interfere much with the blue day average.

However, for different values the plot may be useless when it completely hides a bar.

Pie charts fall apart

We can create two pie charts and put them on the same axes:

1
2
3
4
5
6
labels = 'Cats', 'Dogs'
sizes = [65, 30]

fig, ax = plt.subplots()
ax.pie(sizes, labels=labels)
ax.pie([30, 80], labels=("Apples", "Oranges"))

Unfortunately, the result is a totally useless combination that no longer has any meaning:

We now have 4 labels on one pie chart with two different colours.

Manually layout your bar charts

If we want a bar chart with the bars nicely placed next to each other, we need to do a lot of work by hand. We need to convert our data into a structure that works for Matplotlib and then we need to calculate the position of each bar. The documentation offers us a nice example that I slightly modified by using the average temperatures from Bern instead of a pinguin population:

import numpy as np
months = ['January', 'February', 'March', 'April', 'May', 'June']
temp_average = {
    'day': np.array([3.4, 5.2, 10.3, 14.5, 18.6, 22.5]),
    'night': np.array([-2.9, -2.8, 0.3, 3.4, 7.6, 11.3])
}

x = np.arange(len(months))  # the label locations
width = 0.25  # the width of the bars
multiplier = 0

fig, ax = plt.subplots(constrained_layout=True)

for attribute, measurement in temp_average.items():
    offset = width * multiplier
    rects = ax.bar(x + offset, measurement, width, label=attribute)
    ax.bar_label(rects, padding=3)
    multiplier += 1

# Add some text for labels, title and custom x-axis tick labels, etc.
ax.set_ylabel('Ø Temperature (°C)')
ax.set_title('Temperature averages in Bern, Switzerland')
ax.set_xticks(x + width, months)
ax.legend(loc='upper left', ncols=3)
ax.set_ylim(-5, 25)

plt.show()

This creates us a plot with the day and night average temperatures next to each other:

A plot with bars next to each other instead of on top of each other.

Next

It depends very much on your data and on the type of diagram whether Matplotlib can create a useful combined diagram. There is always the option of doing the low-level work on your own, but we see that Matplotlib reaches its limits of giving us a nice looking plot without much effort.

Next week we will explore NetworkX before we continue with the plot functions of Pandas to see where we can use an abstraction for Matplotlib to get better results.