Reputation: 1565
I have a plot with 2 subplots, all sharing corresponding graphs, i.e. same label for same color. I want to have one legend over the top of the plots, extending over both subplots. Similar to the following code:
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-1,1,1000)
y1 = x
y2 = 0.1*x**2
y3 = x**3
y4 = x**4
y5 = x**5
fig, grid = plt.subplots(1,2,sharex="col", sharey="row")
fig.subplots_adjust(wspace=0, hspace=0)
grid[0].plot(x,y1, label='1')
grid[0].plot(x,y2, label='2')
grid[0].plot(x,y3, label='3')
grid[0].plot(x,y4, label='4')
grid[0].plot(x,y5, label='5')
grid[1].plot(x,y1, label='1')
grid[0].legend(bbox_to_anchor=(0., 1.02, 1., .102), loc=3, ncol=5, borderaxespad=0.)
plt.show()
This example looks almost good. The only problem is that the legend extends from the beginning of the first plot and ends over the middle of the second one. However, I would like the legend to extend over both plots. How can I do that?
Note: Original problem uses 2x3 grid (2 rows, 3 columns).
Upvotes: 1
Views: 2606
Reputation: 339052
In principle everything from How to put the legend out of the plot especially this post applies. An easy solution here is to use the figure's subplots parameters to determine the bounding box in figure coordinates of the legend and use the mode="expand"
.
bb = (fig.subplotpars.left, fig.subplotpars.top+0.02,
fig.subplotpars.right-fig.subplotpars.left,.1)
grid[0].legend(bbox_to_anchor=bb, mode="expand", loc="lower left",
ncol=5, borderaxespad=0., bbox_transform=fig.transFigure)
Upvotes: 3
Reputation: 2240
You can try using something like figlegend
.
fig, grid = plt.subplots(1,2,sharex="col", sharey="row")
fig.subplots_adjust(wspace=0, hspace=0)
a = grid[0].plot(x,y1)
b = grid[0].plot(x,y2)
c = grid[0].plot(x,y3)
d = grid[0].plot(x,y4)
e = grid[0].plot(x,y5)
f = grid[1].plot(x,y1)
fig.legend((a[0], b[0], c[0], d[0], e[0]), ('label 1', 'label 2', 'label 3', 'label 4', 'label 5'), 'upper center', ncol = 5)
plt.show()
The variables a, b, c, d, e, f
are lists with a single object of type Line2D
. Alternatively, you can continue to assign labels the way you have done and then just call that property like so
fig.legend((a[0], b[0], c[0], d[0], e[0]), (a[0]._label, b[0]._label, c[0]._label, d[0]._label, e[0]._label), 'upper center', ncol = 5)
Upvotes: 1