-1

I`d like to have a multiline figure with a dataframe.

Original data is as following:

from numpy.random import randn
import numpy as np

df=pd.DataFrame()
df['Years']=range(1995,2013)
np.random.seed(0)
df['Goverment']=randn(len(df.Years))
df['Household']=randn(len(df.Years))
df['Corporate']=randn(len(df.Years))
print(df)

and I want to set the legend along fully the bound pf figure box. I referred to the answer of @Joe Kington but this problem hasn`t been solved.

For plotting:

import matplotlib.pyplot as plt
fig = plt.figure(figsize=(10,6))
ax = plt.subplot(111)
ax.plot(df.Years, df.Government,ls='--',label='Goverment',color='black')
ax.plot(df.Years,df.Household,ls=':',label='Household',color='black')
ax.plot(df.Years,df.Corporate,ls='-',label='Corporate',color='black')
plt.xlabel("common X")

box = ax.get_position()
ax.set_position([box.x0, box.y0 + box.height * 0.1,
                 box.width, box.height * 1])

# Put a legend below current axis
ax.legend(loc='upper center', bbox_to_anchor=(0.5, -0.1),borderaxespad=1,mode='expand',ncol=3)
plt.show()

and the following is my result. Apparently the mode='expand' doesn`t work here. enter image description here

My questions are: 1. Why the values on X axis are not integral but floats? 2. How to expand the legend box into one line instrad fully along the bound of box?


The ideal legend box should be:

enter image description here

IsaIkari
  • 1,002
  • 16
  • 31
  • 2
    `ax.legend` takes an `ncol` argument that will do this for you – Andrew Dec 11 '18 at 14:35
  • Copying the last section of Joe's answer that you link to gives the desired output for the legend. You are using slightly different values and therefore get a slightly different result... – DavidG Dec 11 '18 at 14:43

1 Answers1

1

The difference is indeed that you use the mode='expand'. Now this will tell the legend to expand in its bounding box. However the bounding box has no extent, it is a single point. The legend will hence expand inside a zero-width box and hence become shrunk to zero width itself.

The solution is to specify a bounding box with 4 coordinates (i.e. a true box). In principle this should also be explained in my answer to the linked question. So here we would use axes coordinates for the bbox_transform and make the box one unit in axes coordinates wide.

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(10)

fig = plt.figure()
fig.subplots_adjust(bottom=0.2, top=0.95)
ax = plt.subplot(111)

for i in range(5):
    line, = ax.plot(x, i * x, label='$y = %ix$'%i)

# Put a legend below current axis
ax.legend(loc="upper center", mode='expand',
          bbox_to_anchor=(0,-0.2,1,.1), bbox_transform=ax.transAxes,
          fancybox=True, shadow=True, ncol=5)

plt.show()

enter image description here

ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712