4

I'm using an ipython notebook (python 2) and am plotting both a barchart and a line plot on the same plot. There are two series (NPS and Count Ratings). However, when I try to display the legend, it only shows a legend for the second series.

Below is my code:

ax=nps_funding_month[35:][nps_funding_month['count_ratings']>=100].set_index('funding_month')['nps_percentage'].\
plot(kind='line',color='green',label='NPS')

plt.ylabel('Net Promoter Score')

ax=nps_funding_month[35:][nps_funding_month['count_ratings']>=100].set_index('funding_month')['count_ratings'].\
plot(kind='bar',secondary_y=True,label='Count of Ratings')

plt.ylabel('Count Ratings')

plt.legend()

plt.title('Net Promoter Score by Funding Month\n(Only Funding Months with at Least 100 Reviews)')

Picture of Output

ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
Pcarlitz
  • 223
  • 1
  • 5
  • 17
  • Would you mind reading [How to make good reproducible pandas examples](https://stackoverflow.com/questions/20109391/how-to-make-good-reproducible-pandas-examples)? – ImportanceOfBeingErnest Aug 19 '17 at 23:49

1 Answers1

2

The following code

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

df=pd.DataFrame({"x" : np.arange(5),
                 "a" : np.exp(np.linspace(3,5,5)),
                 "b" : np.exp(-np.linspace(-1,0.5,5)**2)})

ax=df.plot(x="x", y="a", kind='line',color='green',label='NPS')

plt.ylabel('Net Promoter Score')

ax2 = df.plot(x="x", y="b", kind='bar',secondary_y=True,label='Count of Ratings', ax=ax)

plt.ylabel('Count Ratings')

plt.title('Superlongtitle that is not needed')  
plt.show()

produces

enter image description here

Note that the first axes is given as argument to the second pandas plot (ax=ax) and no legend is added via pyplot (it comes automatically through pandas).

The problem may then be that the legend is hidden by the bars. The reason for that is that the legend resides in the first (lower) axes. There are two options.

  1. We could move it to the secondary axes and then also change its location.

    leg = ax.get_legend()
    leg.remove()        # remove it from ax
    ax2.add_artist(leg) # add it to ax2
    leg._set_loc(4)
    

    Where the the loc 4 means "lower left" and is one of the codes to place the legend.

  2. We can move it out of the plot, (as in How to put the legend out of the plot)

    leg._set_loc(2)
    leg.set_bbox_to_anchor((1.1,1))
    ax.figure.subplots_adjust(right=0.6) # make space for the legend outside
    
ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
  • Awesome. This works to an extent (the legend overlaps with one of the bars). Could you add to this how you would move the legend somewhere else? Much appreciated! – Pcarlitz Aug 20 '17 at 00:33
  • Also note that the method presented in this answer only works when the same dataframe is used for both plots. In case two different dataframes are used, refer to the answers from [this question](https://stackoverflow.com/questions/21988196/legend-only-shows-one-label-when-plotting-with-pandas). – ImportanceOfBeingErnest Aug 20 '17 at 09:41
  • Wow thanks. I've been searching SO for days to figure this out. – Pcarlitz Aug 21 '17 at 00:12
  • As of pandas 1.3.3 this example no longer works. You should replace `label` with `legend`. – jfaleiro Oct 20 '21 at 21:29