|
From: Chris W. <ch...@si...> - 2008-03-17 11:42:38
|
Hi All,
How would I go about placing the legend outside the plot area?
All the parameters to legend seem to place the legend somewhere within
the plot and I'd like to place it outside the plot, either above, below
or, most commonly, to the right, in the same way as the Excel legend
positions allow.
cheers,
Chris
--
Simplistix - Content Management, Zope & Python Consulting
- http://www.simplistix.co.uk
|
|
From: Matthias M. <Mat...@gm...> - 2008-03-17 12:00:23
|
Hello Chris, I'm not sure if there was an example in matplotlib, but the following works for me: --------------------------------------------------------------------- from pylab import * figure() subplot(111) subplots_adjust(right=0.7) plot(arange(10), label='linear') plot(arange(10)**2, label='quadratic') legend(loc=(1.1,0.5)) show() ------------------------------------------------------------------------ I hope this is useful to you. best regards Matthias On Monday 17 March 2008 12:42, Chris Withers wrote: > Hi All, > > How would I go about placing the legend outside the plot area? > > All the parameters to legend seem to place the legend somewhere within > the plot and I'd like to place it outside the plot, either above, below > or, most commonly, to the right, in the same way as the Excel legend > positions allow. > > cheers, > > Chris |
|
From: Chris W. <ch...@si...> - 2008-03-17 16:13:21
|
Hi Matthias,
Matthias Michler wrote:
> I'm not sure if there was an example in matplotlib, but the following works
> for me:
> ---------------------------------------------------------------------
> from pylab import *
> figure()
> subplot(111)
> subplots_adjust(right=0.7)
> plot(arange(10), label='linear')
> plot(arange(10)**2, label='quadratic')
> legend(loc=(1.1,0.5))
> show()
> ------------------------------------------------------------------------
Thanks for this. This is exactly what I was after except that the legend
now appears about 25% off the right hand of the screen or whatever I
save the figure to.
How can I have the legend as placed above but with the whole of it showing?
cheers,
Chris
--
Simplistix - Content Management, Zope & Python Consulting
- http://www.simplistix.co.uk
|
|
From: Matthias M. <Mat...@gm...> - 2008-03-17 16:47:17
|
Hi Chris, sorry I don't understand what you are exactly looking for. Maybe you could explain it once more. In general I think all one can do is to play around with the parameters in 'subplots_adjust' and the location in 'legend' to get the best result. I'm not an expert but I think there's no default behaviour covering all needs (outside the axes and best located), because for example the legend width is influenced by the length of the labels. much effort and best regards Matthias On Monday 17 March 2008 17:13, Chris Withers wrote: > Hi Matthias, > > Matthias Michler wrote: > > I'm not sure if there was an example in matplotlib, but the following > > works for me: > > --------------------------------------------------------------------- > > from pylab import * > > figure() > > subplot(111) > > subplots_adjust(right=0.7) > > plot(arange(10), label='linear') > > plot(arange(10)**2, label='quadratic') > > legend(loc=(1.1,0.5)) > > show() > > ------------------------------------------------------------------------ > > Thanks for this. This is exactly what I was after except that the legend > now appears about 25% off the right hand of the screen or whatever I > save the figure to. > > How can I have the legend as placed above but with the whole of it showing? > > cheers, > > Chris |
|
From: Chris W. <ch...@si...> - 2008-03-17 17:23:49
|
Matthias Michler wrote:
> sorry I don't understand what you are exactly looking for. Maybe you could
> explain it once more.
Well, what you provided was pretty close, it's just that the legend was
partly placed outside the figure...
> In general I think all one can do is to play around with the parameters
> in 'subplots_adjust' and the location in 'legend' to get the best result.
> I'm not an expert but I think there's no default behaviour covering all needs
> (outside the axes and best located), because for example the legend width is
> influenced by the length of the labels.
Right, this is the problem. The location your example provided is
perfect, except that I may have no control over the length of the legend
text, and so need to find a way to make sure the figure size is such
that the legend doesn't end up being half off the figure...
Anyone know how to do that?
(and thanks to Matthias for all his help! :-) )
cheers,
Chris
--
Simplistix - Content Management, Zope & Python Consulting
- http://www.simplistix.co.uk
|
|
From: Eric F. <ef...@ha...> - 2008-03-17 21:22:33
|
It sounds like what you want it the pyplot figlegend command:
def figlegend(handles, labels, loc, **kwargs):
"""
Place a legend in the figure. Labels are a sequence of
strings, handles is a sequence of line or patch instances, and
loc can be a string r an integer specifying the legend
location
USAGE:
legend( (line1, line2, line3),
('label1', 'label2', 'label3'),
'upper right')
See help(legend) for information about the location codes
A matplotlib.legend.Legend instance is returned
"""
or you could directly use the Figure.legend method. The relevant part
of the docstring regarding placement in the figure is here:
The LOC location codes are
'best' : 0, (currently not supported for figure legends)
'upper right' : 1,
'upper left' : 2,
'lower left' : 3,
'lower right' : 4,
'right' : 5,
'center left' : 6,
'center right' : 7,
'lower center' : 8,
'upper center' : 9,
'center' : 10,
loc can also be an (x,y) tuple in figure coords, which
specifies the lower left of the legend box. figure coords are
(0,0) is the left, bottom of the figure and 1,1 is the right,
top.
Eric
Chris Withers wrote:
> Matthias Michler wrote:
>> sorry I don't understand what you are exactly looking for. Maybe you could
>> explain it once more.
>
> Well, what you provided was pretty close, it's just that the legend was
> partly placed outside the figure...
>
>> In general I think all one can do is to play around with the parameters
>> in 'subplots_adjust' and the location in 'legend' to get the best result.
>> I'm not an expert but I think there's no default behaviour covering all needs
>> (outside the axes and best located), because for example the legend width is
>> influenced by the length of the labels.
>
> Right, this is the problem. The location your example provided is
> perfect, except that I may have no control over the length of the legend
> text, and so need to find a way to make sure the figure size is such
> that the legend doesn't end up being half off the figure...
>
> Anyone know how to do that?
>
> (and thanks to Matthias for all his help! :-) )
>
> cheers,
>
> Chris
>
|
|
From: Chris W. <ch...@si...> - 2008-03-18 09:50:55
|
Eric Firing wrote:
> It sounds like what you want it the pyplot figlegend command:
> def figlegend(handles, labels, loc, **kwargs):
This feels like what I should be wanting except:
- why does it need explicit parameters? why can't it pick up its lines
and labels automatically, like legend does?
- it places the legend over the top of the current chart, I want it to
the right, so it doesn't obscure the information on the chart...
> or you could directly use the Figure.legend method.
How does this differ from the normal legend command?
How do I get hold of a figure to call its legend method?
How does figure.legend interact with subplots?
I have a bout 6 subplots on the same figure(?) and they each need to
have a legend which is not obscuring the data plotted and isn't
obscuring any other figure...
cheers,
Chris
--
Simplistix - Content Management, Zope & Python Consulting
- http://www.simplistix.co.uk
|
|
From: Matthias M. <Mat...@gm...> - 2008-03-18 10:31:22
|
On Tuesday 18 March 2008 10:50, Chris Withers wrote:
> Eric Firing wrote:
> > It sounds like what you want it the pyplot figlegend command:
> > def figlegend(handles, labels, loc, **kwargs):
>
> This feels like what I should be wanting except:
>
> - why does it need explicit parameters? why can't it pick up its lines
> and labels automatically, like legend does?
- I think this could be a good improvement, but i'm not sure if it is easy to
expand the functionality of the axes-legend (pyplot.legend or ax.legend) to
that of a figure-legend(pyplot.figlegend or fig.legend with fig as a figure
instance) without missing something, because there is no axes specified and
therefore it is not obvious which lines should be displayed. In that case the
default behaviour might become to take all lines from all axes and that's not
what one always needs, or isn't it?
In this case one should do it autonomous like:
ax1 = subplot(111)
# some plotting commands
labels = []
for line in ax1.lines:
label = line.get_label()
labels.append(label)
# or in one line:
# labels = [line.get_label() for line in ax1.lines]
figlegend(ax1.lines, labels, 'upper right')
> - it places the legend over the top of the current chart, I want it to
> the right, so it doesn't obscure the information on the chart...
That's true and I have no idea how to overcome that (except for example
subplot_adjust(top=0.8)).
> > or you could directly use the Figure.legend method.
>
> How does this differ from the normal legend command?
> How do I get hold of a figure to call its legend method?
fig=figure()
fig.legend( ... )
and it is wrapped by
figlegend( ... )
and therefore has the same functionality / arguments
and it differs from the axes-legend like explained above ...
> How does figure.legend interact with subplots?
I'm don't know, but maybe it doesn't interact with the axes / subplots at all.
> I have a bout 6 subplots on the same figure(?) and they each need to
> have a legend which is not obscuring the data plotted and isn't
> obscuring any other figure...
I think in that case the axes-legend is the preferred one, but I have no idea
how to ensure that nothing is cover by the legend without difficult tuning of
the parameters or at least ensure that all labels have the same widths.
best regards
Matthias
|
|
From: Chris W. <ch...@si...> - 2008-03-18 16:17:51
|
Matthias Michler wrote:
> - I think this could be a good improvement, but i'm not sure if it is easy to
> expand the functionality of the axes-legend (pyplot.legend or ax.legend) to
> that of a figure-legend(pyplot.figlegend or fig.legend with fig as a figure
> instance) without missing something, because there is no axes specified and
> therefore it is not obvious which lines should be displayed.
True, although if there's only one axes, it's obvious ;-)
(and if there's more than one, it should take an axes as a keyword
parameter)
> In that case the
> default behaviour might become to take all lines from all axes and that's not
> what one always needs, or isn't it?
Who knows, maybe someone would want that? The joy of building generic
tools ;-)
> ax1 = subplot(111)
> # some plotting commands
> labels = []
> for line in ax1.lines:
> label = line.get_label()
> labels.append(label)
> # or in one line:
> # labels = [line.get_label() for line in ax1.lines]
> figlegend(ax1.lines, labels, 'upper right')
Yes, you see, it just feels to me like figlegend should have this code
in it as it's likely to be duplicated every time I need to call figlegend.
Why not just?
figlegend(axes=ax1,'upper right')
>> - it places the legend over the top of the current chart, I want it to
>> the right, so it doesn't obscure the information on the chart...
>
> That's true and I have no idea how to overcome that (except for example
> subplot_adjust(top=0.8)).
Yes, I'm just making do with this for now, but it would be really nice
if MPL supported legends outsite the axes properly.
It would also be good if you didn't have to manually fiddle with
subplot_adjust because you rotated the labels for the x-axis through 90
degrees :-(
>> How does figure.legend interact with subplots?
> I'm don't know, but maybe it doesn't interact with the axes / subplots at all.
'badly' I think is the best summary of the interaction ;-)
> I think in that case the axes-legend is the preferred one, but I have no idea
> how to ensure that nothing is cover by the legend without difficult tuning of
> the parameters or at least ensure that all labels have the same widths.
Yeah :-/ This is where I am... If anyone has any magic code or
suggestions, I'd love to hear 'em ;-)
Chris
--
Simplistix - Content Management, Zope & Python Consulting
- http://www.simplistix.co.uk
|