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.
This post is part of my journey to learn Python. You can find the other parts of this series here. You find the code for this post in my PythonFriday repository on GitHub.
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:
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:
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:
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
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:
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.