If you call
ax.legend() more than once, the first legend is removed and a new one is drawn. According the official documentation:
This has been done so that it is possible to call legend() repeatedly to update the legend to the latest handles on the Axes
Fear not, though: It is still quite simple to add a second legend (or third, or fourth...) to an axes. In the example here, we plot two lines, then plot markers on their respective maxima and minima. One legend is for the lines, and the other is for the markers.
import matplotlib.pyplot as plt import numpy as np # Generate data for plotting: x = np.linspace(0,2*np.pi,100) y0 = np.sin(x) y1 = .9*np.sin(.9*x) # Find their maxima and minima and store maxes = np.empty((2,2)) mins = np.empty((2,2)) for k,y in enumerate([y0,y1]): maxloc = y.argmax() maxes[k] = x[maxloc], y[maxloc] minloc = y.argmin() mins[k] = x[minloc], y[minloc] # Instantiate figure and plot fig = plt.figure() ax = fig.add_subplot(111) ax.plot(x,y0, label='y0') ax.plot(x,y1, label='y1') # Plot maxima and minima, and keep references to the lines maxline, = ax.plot(maxes[:,0], maxes[:,1], 'r^') minline, = ax.plot(mins[:,0], mins[:,1], 'ko') # Add first legend: only labeled data is included leg1 = ax.legend(loc='lower left') # Add second legend for the maxes and mins. # leg1 will be removed from figure leg2 = ax.legend([maxline,minline],['max','min'], loc='upper right') # Manually add the first legend back ax.add_artist(leg1)
The key is to make sure you have references to the legend objects. The first one you instantiate (
leg1) is removed from the figure when you add the second one, but the
leg1 object still exists and can be added back with
The really great thing is that you can can still manipulate both legends. For example, add the following to the bottom of the above code:
Finally, it's worth mentioning that in the example only the lines were given labels when plotted, meaning that
ax.legend() adds only those lines to the
leg1. The legend for the markers (
leg2) therefore required the lines and labels as arguments when it was instantiated. We could have, alternatively, given labels to the markers when they were plotted too. But then both calls to
ax.legend would have required some extra arguments so that each legend contained only the items we wanted.