Secondary axis with twinx(): how to add to legend? Secondary axis with twinx(): how to add to legend? python python

Secondary axis with twinx(): how to add to legend?


You can easily add a second legend by adding the line:

ax2.legend(loc=0)

You'll get this:

enter image description here

But if you want all labels on one legend then you should do something like this:

import numpy as npimport matplotlib.pyplot as pltfrom matplotlib import rcrc('mathtext', default='regular')time = np.arange(10)temp = np.random.random(10)*30Swdown = np.random.random(10)*100-10Rn = np.random.random(10)*100-10fig = plt.figure()ax = fig.add_subplot(111)lns1 = ax.plot(time, Swdown, '-', label = 'Swdown')lns2 = ax.plot(time, Rn, '-', label = 'Rn')ax2 = ax.twinx()lns3 = ax2.plot(time, temp, '-r', label = 'temp')# added these three lineslns = lns1+lns2+lns3labs = [l.get_label() for l in lns]ax.legend(lns, labs, loc=0)ax.grid()ax.set_xlabel("Time (h)")ax.set_ylabel(r"Radiation ($MJ\,m^{-2}\,d^{-1}$)")ax2.set_ylabel(r"Temperature ($^\circ$C)")ax2.set_ylim(0, 35)ax.set_ylim(-20,100)plt.show()

Which will give you this:

enter image description here


I'm not sure if this functionality is new, but you can also use the get_legend_handles_labels() method rather than keeping track of lines and labels yourself:

import numpy as npimport matplotlib.pyplot as pltfrom matplotlib import rcrc('mathtext', default='regular')pi = np.pi# fake datatime = np.linspace (0, 25, 50)temp = 50 / np.sqrt (2 * pi * 3**2) \        * np.exp (-((time - 13)**2 / (3**2))**2) + 15Swdown = 400 / np.sqrt (2 * pi * 3**2) * np.exp (-((time - 13)**2 / (3**2))**2)Rn = Swdown - 10fig = plt.figure()ax = fig.add_subplot(111)ax.plot(time, Swdown, '-', label = 'Swdown')ax.plot(time, Rn, '-', label = 'Rn')ax2 = ax.twinx()ax2.plot(time, temp, '-r', label = 'temp')# ask matplotlib for the plotted objects and their labelslines, labels = ax.get_legend_handles_labels()lines2, labels2 = ax2.get_legend_handles_labels()ax2.legend(lines + lines2, labels + labels2, loc=0)ax.grid()ax.set_xlabel("Time (h)")ax.set_ylabel(r"Radiation ($MJ\,m^{-2}\,d^{-1}$)")ax2.set_ylabel(r"Temperature ($^\circ$C)")ax2.set_ylim(0, 35)ax.set_ylim(-20,100)plt.show()


From matplotlib version 2.1 onwards, you may use a figure legend. Instead of ax.legend(), which produces a legend with the handles from the axes ax, one can create a figure legend

fig.legend(loc="upper right")

which will gather all handles from all subplots in the figure. Since it is a figure legend, it will be placed at the corner of the figure, and the loc argument is relative to the figure.

import numpy as npimport matplotlib.pyplot as pltx = np.linspace(0,10)y = np.linspace(0,10)z = np.sin(x/3)**2*98fig = plt.figure()ax = fig.add_subplot(111)ax.plot(x,y, '-', label = 'Quantity 1')ax2 = ax.twinx()ax2.plot(x,z, '-r', label = 'Quantity 2')fig.legend(loc="upper right")ax.set_xlabel("x [units]")ax.set_ylabel(r"Quantity 1")ax2.set_ylabel(r"Quantity 2")plt.show()

enter image description here

In order to place the legend back into the axes, one would supply a bbox_to_anchor and a bbox_transform. The latter would be the axes transform of the axes the legend should reside in. The former may be the coordinates of the edge defined by loc given in axes coordinates.

fig.legend(loc="upper right", bbox_to_anchor=(1,1), bbox_transform=ax.transAxes)

enter image description here