4

I am plotting a pandas dataframe with a second y-axis via pandas plotting interface as described in the documentation like this:

df = pd.DataFrame(np.random.randn(24*3, 3),
                  index=pd.date_range('1/1/2019', periods=24*3, freq='h'))
df.columns = ['A (left)', 'B (right)', 'C (right)']
ax = df.plot(secondary_y=['B (right)', 'C (right)'], mark_right=False)
ax.set_ylabel('A scale')
ax.right_ax.set_ylabel('BC scale')
ax.legend(loc='upper right')
plt.show()

which yields enter image description here As it can be seen, the legend looses entries when I set the position using ax.legend(loc='upper right').

Does anyone know how I can set the legend position and keep all entries?

Thanks in advance!

Cord Kaldemeyer
  • 6,405
  • 8
  • 51
  • 81
  • @Bazingaa: Your second possible duplicate is directly related to matplotlib. I don't see a duplicate here because I am using pandas plotting interface. Your first possible duplicate is indeed related to my question as one of the answers relates to the pandas plotting interface. Maybe, that is why I did not find anything on my question.. – Cord Kaldemeyer Jan 08 '19 at 13:00
  • I could of course delete my question but would think that the combination of a direct pandas-related question and answer has its own value. – Cord Kaldemeyer Jan 08 '19 at 13:01
  • @Bazingaa: Sorry, but I do not think that this is a duplicate because I specifically ask for a solution using the pandas plotting API. The question/answer you refer to asks for a direct matplotlib solution and only contains an answer with the pandas solution. – Cord Kaldemeyer Jan 08 '19 at 18:01

1 Answers1

10

We can use .get_legend_handles_labels() for a more correct solution:

np.random.seed(42)

df = pd.DataFrame(np.random.randn(24*3, 3),
                  index=pd.date_range('1/1/2019', periods=24*3, freq='h'))
df.columns = ['A (left)', 'B (right)', 'C (right)']
ax = df.plot(secondary_y=['B (right)', 'C (right)'], mark_right=False)
ax.set_ylabel('A scale')
ax.right_ax.set_ylabel('BC scale')

h1, l1 = ax.get_legend_handles_labels()
h2, l2 = ax.right_ax.get_legend_handles_labels()
ax.legend(h1+h2, l1+l2, loc=1)

enter image description here

The reason we need to use that method is because ax and ax.right_ax each have their own legend and simply setting them to the same location will render them on top of each other.

Charles Landau
  • 4,187
  • 1
  • 8
  • 24
  • Thanks a lot for your help! – Cord Kaldemeyer Jan 08 '19 at 13:01
  • Is it also possible to split the labels to the axes e.g. to put "A (left)" on the upper left and "B (right) C (right)" to the upper right? Something similar is described here but with a figure: https://stackoverflow.com/questions/46011940/how-to-plot-two-pandas-time-series-on-same-plot-with-legends-and-secondary-y-axi – Cord Kaldemeyer Jan 08 '19 at 13:43
  • Got it: ax.legend(h1, l1, loc='upper left'); ax.right_ax.legend(h2, l2, loc='upper right') Thanks a lot, again! – Cord Kaldemeyer Jan 08 '19 at 13:45
  • @CordKaldemeyer that's more or less what I was thinking, glad this worked out for you! – Charles Landau Jan 08 '19 at 13:47
  • Do you know if there is the possibility to use different markers for the left and right axes? – Cord Kaldemeyer Jan 15 '19 at 10:21