pythonmatplotliblegendmultiple-axes

Matplotlib: how to show legend for bar chart and line on 2 separate axes?


I am plotting a bar chart on the left axis and a line chart on the right axis. How can I show the legend for both in the same legend box?

With the code below, I get two separate legend boxes; also, I need to specify the location of the second legend manually, with lots of trial-and-error, otherwise it overlaps the first one.

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

df=pd.DataFrame()
df["bar"]=[40,35,50,45]
df["line"]=[.5,.3,.2,.6]

fig,ax=plt.subplots(2)

l1 = ax[0].bar(df.index, df["bar"], label='my bar chart (left axis)', color='royalblue', width = 0.55)
ax0b=ax[0].twinx()
l2 = ax0b.plot(df.index,  df['line'], label='my line (right axis)',color='tomato',marker='.', ls='dashed')

ax[0].legend(loc='upper left', fancybox=True, title='My title')
ax0b.legend(bbox_to_anchor=(0.155,0.8), loc=1)    
plt.show()

If I had two lines on two different axes, instead of a bar chart and a line chart, I'd do:

myl=l1+l2
labs=[l.get_label() for l in myl]
ax[0].legend(myl, labs, loc='upper left')

But this doesn't work in my case. I get:

myl=l1+l2
TypeError: can only concatenate tuple (not "list") to tuple

which I imagine must be because bar() and plot() return two different objects which cannot be concatenated.


Solution

  • The good thing about python errors is that they most often can be taken literally and directly tell you the problem.

    "TypeError" tells you that you have a problem of types. You may print the types:

    print(type(l1)) # <class 'matplotlib.container.BarContainer'>
    print(type(l2)) # <type 'list'>
    

    Now, "can only concatenate tuple (not "list") to tuple" tells you that you cannot add a barcontainer to a list.

    Easy solution: Add two lists:

    myl=[l1]+l2