I'm developing a Web application and want to display a figure and its legend in different locations on the page. Which means I need to save the legend as a separate png file. Is this possible in Matplotlib in a more or less straightforward way?
Axes' to the figure as part of a subplot arrangement, using the add_subplot() method at nrow=1, ncols=1 and at index=1. Create line1 and line2 using x, y and y1 points. Place the legend for line1 and line2, set ordered labels, put at center location. Save the figure only with legend using the savefig() method.
In Matplotlib, to set a legend outside of a plot you have to use the legend() method and pass the bbox_to_anchor attribute to it. We use the bbox_to_anchor=(x,y) attribute. Here x and y specify the coordinates of the legend.
To change the position of a legend in Matplotlib, you can use the plt. legend() function. The default location is “best” – which is where Matplotlib automatically finds a location for the legend based on where it avoids covering any data points.
This could work:
import pylab fig = pylab.figure() figlegend = pylab.figure(figsize=(3,2)) ax = fig.add_subplot(111) lines = ax.plot(range(10), pylab.randn(10), range(10), pylab.randn(10)) figlegend.legend(lines, ('one', 'two'), 'center') fig.show() figlegend.show() figlegend.savefig('legend.png')
You may limit the saved region of a figure to the bounding box of the legend using the bbox_inches
argument to fig.savefig
. Below to versions of a function which you can simply call with the legend you want to save as argument. You may either use the legend created in the original figure here (and remove it afterwards, legend.remove()
) or you may create a new figure for the legend and simply use the function as it is.
In case the complete legend shall be saved, the bounding box supplied to the bbox_inches
argument would be simply the transformed bounding box of the legend. This works well if the legend has no border around it.
import matplotlib.pyplot as plt colors = ["crimson", "purple", "gold"] f = lambda m,c: plt.plot([],[],marker=m, color=c, ls="none")[0] handles = [f("s", colors[i]) for i in range(3)] labels = colors legend = plt.legend(handles, labels, loc=3, framealpha=1, frameon=False) def export_legend(legend, filename="legend.png"): fig = legend.figure fig.canvas.draw() bbox = legend.get_window_extent().transformed(fig.dpi_scale_trans.inverted()) fig.savefig(filename, dpi="figure", bbox_inches=bbox) export_legend(legend) plt.show()
If there is a border around the legend, the above solution may be suboptimal. In this case it makes sense to extend the bounding box by some pixels to include the border to its full.
import numpy as np import matplotlib.pyplot as plt colors = ["crimson", "purple", "gold"] f = lambda m,c: plt.plot([],[],marker=m, color=c, ls="none")[0] handles = [f("s", colors[i]) for i in range(3)] labels = colors legend = plt.legend(handles, labels, loc=3, framealpha=1, frameon=True) def export_legend(legend, filename="legend.png", expand=[-5,-5,5,5]): fig = legend.figure fig.canvas.draw() bbox = legend.get_window_extent() bbox = bbox.from_extents(*(bbox.extents + np.array(expand))) bbox = bbox.transformed(fig.dpi_scale_trans.inverted()) fig.savefig(filename, dpi="figure", bbox_inches=bbox) export_legend(legend) plt.show()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With