I have access to the figure instance fig = pylab.gcf()
. I know that in this figure there is a legend and I can access it via myLegend = fig.gca().legend_
. Now I want to change the properties of the legend. Some of them I have access via setters like myLegend.set_frame_on(True)
.
When the legend is created it accepts a number of keyword arguments:
class matplotlib.legend.Legend(parent, handles, labels, loc=None, numpoints=None, markerscale=None, scatterpoints=None, scatteryoffsets=None, prop=None, fontsize=None, borderpad=None, labelspacing=None, handlelength=None, handleheight=None, handletextpad=None, borderaxespad=None, columnspacing=None, ncol=1, mode=None, fancybox=None, shadow=None, title=None, framealpha=None, bbox_to_anchor=None, bbox_transform=None, frameon=None, handler_map=None)
How can I modify all the keyword arguments in the legend after the legend is created?
One of the problematic ones is numpoints
(number of markers in a legend, default is 2). Below is the example how I want to change it:
This shows how I want to program it
import pylab
pylab.plot(0,0,'ro', label = 'one point')
pylab.legend(loc = "lower left")
# no modifications above this line
setattr(pylab.gcf().gca().legend_, 'numpoints',1)
pylab.show()
This shows how I want it to look like
import pylab
pylab.plot(0,0,'ro', label = 'one point')
pylab.legend(numpoints = 1, loc = "lower left")
pylab.show()
I have cheked the source code, there is a numpoint variable that is changed, but the upper case is not updated to screen. What am I missing?
I've written a function modify_legend
which modifies a legend after it has been created. It basically reads all the parameters from the already created legend, updates it with the key-value parameters you provided and calls legend(...)
with all possible parameters again.
Your problem would then be solved with:
import pylab
pylab.plot(0,0,'ro', label = 'one point')
pylab.legend(loc = "lower left")
modify_legend(numpoints = 1)
pylab.show()
Here's the code for modify_legend
:
def modify_legend(**kwargs):
import matplotlib as mpl
l = mpl.pyplot.gca().legend_
defaults = dict(
loc = l._loc,
numpoints = l.numpoints,
markerscale = l.markerscale,
scatterpoints = l.scatterpoints,
scatteryoffsets = l._scatteryoffsets,
prop = l.prop,
# fontsize = None,
borderpad = l.borderpad,
labelspacing = l.labelspacing,
handlelength = l.handlelength,
handleheight = l.handleheight,
handletextpad = l.handletextpad,
borderaxespad = l.borderaxespad,
columnspacing = l.columnspacing,
ncol = l._ncol,
mode = l._mode,
fancybox = type(l.legendPatch.get_boxstyle())==mpl.patches.BoxStyle.Round,
shadow = l.shadow,
title = l.get_title().get_text() if l._legend_title_box.get_visible() else None,
framealpha = l.get_frame().get_alpha(),
bbox_to_anchor = l.get_bbox_to_anchor()._bbox,
bbox_transform = l.get_bbox_to_anchor()._transform,
frameon = l._drawFrame,
handler_map = l._custom_handler_map,
)
if "fontsize" in kwargs and "prop" not in kwargs:
defaults["prop"].set_size(kwargs["fontsize"])
mpl.pyplot.legend(**dict(defaults.items() + kwargs.items()))
Notes on the code:
Legend
object, others (like title
, fancybox
) required some 'artistics'. You could check matplotlib.legend.Legend.__init__
to see how and why it's done.fontsize
parameter is used for overriding the font size when the legend was originally created with a prop
, as prop
usually overwrites fontsize
.bbox_to_anchor
and bbox_transform
-parameters), so feel free to try out and improve the code :)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