90

How is it possible to put legend outside the plot?

import pandas as pd
import matplotlib.pyplot as plt
a = {'Test1': {1: 21867186, 4: 20145576, 10: 18018537},
    'Test2': {1: 23256313, 4: 21668216, 10: 19795367}}

d = pd.DataFrame(a).T
#print d

f = plt.figure()

plt.title('Title here!', color='black')
plt.legend(loc='center left', bbox_to_anchor=(1, 0.5))
d.plot(kind='bar', ax=f.gca())
plt.show()
user977828
  • 7,259
  • 16
  • 66
  • 117
  • 26
    Actually it's not a complete duplicate...the question is asking specifically for Pandas. The response below shows how to assign an axis to a plot function call from `pandas.DataFrame.plot` which makes it possible to apply the `matplotlib.pyplot` refinements. – slushy Aug 23 '15 at 13:18
  • 4
    Yeah, this isn't a duplicate and it's annoying that it's marked as such. – ferrouswheel Feb 15 '18 at 01:52
  • 2
    This is NOT a duplicate, as it is for Pandas `.plot`. The solution is outlined below thanks to @matt_harrison, but to summarize: where you have `d.plot(kind='bar', ax=f.gca())`, change this to `d.plot(kind='bar', ax=f.gca()).legend(bbox_to_anchor=(1,1))` – Alex Jan 04 '20 at 01:43
  • Check this folks: https://stackoverflow.com/questions/4700614/how-to-put-the-legend-out-of-the-plot It has really good discussion/answers and this question is *pretty much* a duplicate of that one, if you know minimal pandas/matplotlib. – eric Nov 09 '20 at 16:41

4 Answers4

137

I think you need to call plot before you add the calling legend.

import pandas as pd
import matplotlib.pyplot as plt
a = {'Test1': {1: 21867186, 4: 20145576, 10: 18018537},
    'Test2': {1: 23256313, 4: 21668216, 10: 19795367}}

d = pd.DataFrame(a).T
#print d

f = plt.figure()

plt.title('Title here!', color='black')
d.plot(kind='bar', ax=f.gca())
plt.legend(loc='center left', bbox_to_anchor=(1.0, 0.5))
plt.show()

----- Panda solution If you are using pandas Dataframe.plot

dataframe_var.plot.bar().legend(loc='center left',bbox_to_anchor=(1.0, 0.5));
Rohit Nandi
  • 768
  • 10
  • 14
Phil
  • 2,080
  • 2
  • 12
  • 13
  • 2
    However, half of the legend is now not in picture? How is it possible to fix it? – user977828 May 09 '14 at 04:13
  • It's really a separate question, but you could try `f.subplots_adjust(right=0.8)`. – Phil May 09 '14 at 15:06
  • 36
    If you just want to move the legend, you can take advantage of the fact that ``.plot`` returns a matplotlib axis and add ``.legend(bbox_to_anchor=(1,1))`` to the end of your plot line of code – Matt Harrison Nov 20 '17 at 17:48
  • 6
    The comment by @mattharrison should be the answer. – Brick Dec 19 '17 at 17:00
  • 7
    I don't think it is a separate question, the point is to move the legend, I don't see why would the legend suddenly be half-cut after it has been moved. – layser Mar 10 '18 at 15:16
  • 1
    Not working for me the legend is outside of the plot even with the `bbox_to_anchor` stuff. Note there are some really good discussions of this issue at the answers to this question: https://stackoverflow.com/questions/4700614/how-to-put-the-legend-out-of-the-plot – eric Nov 09 '20 at 16:39
14

I am able to place the legend outside the chart with the following snippet based on OP's question:

import pandas as pd
import matplotlib.pyplot as plt
a = {'Test1': {1: 21867186, 4: 20145576, 10: 18018537},
    'Test2': {1: 23256313, 4: 21668216, 10: 19795367}}

df = pd.DataFrame(a).T

ax = df.plot.bar()
ax.set_title("Title here!",color='black')
ax.legend(bbox_to_anchor=(1.0, 1.0))
ax.plot()

How it appears in my notebook: enter image description here

You can then modify the anchor values to adjust its placement as needed. The anchor point would be the bottom left hand corner of this chart.

CodeBender
  • 35,668
  • 12
  • 125
  • 132
4

This is working for me

ax = df.plot(kind='bar')
ax.yaxis.set_major_formatter(mtick.PercentFormatter())
ax.legend(loc='center left', bbox_to_anchor=(1.0, 0.5)) #here is the magic
Rami Alloush
  • 2,308
  • 2
  • 27
  • 33
3

I felt more easy to use this one, any feedback appreciated

df.plot(kind='area')
plt.legend(loc=(1.01,.35)) #here I tried to keep it outside middle right