Search code examples
pythonmatplotlibbar-chartdata-sciencedata-analysis

Using Hlines ruins legends in Matplotlib


I'm struggling to adjust my plot legend after adding the axline/ hline on 100 level in the graph.(screenshot added)

if there's a way to run this correctly so no information will be lost in legend, and maybe add another hline and adding it to the legend.

adding the code here, maybe i'm not writing it properly.

fig, ax1 = plt.subplots(figsize = (9,6),sharex=True)

BundleFc_Outcome['Spend'].plot(kind = 'bar',color = 'blue',width = 0.4, ax = ax1,position = 1)
#
# Make the y-axis label, ticks and tick labels match the line color.
ax1.set_ylabel('SPEND', color='b', size = 18)
ax1.set_xlabel('Bundle FC',color='w',size = 18)

ax2 = ax1.twinx()
ax2.set_ylabel('ROAS', color='r',size = 18)
ax1.tick_params(axis='x', colors='w',size = 20)
ax2.tick_params(axis = 'y', colors='w',size = 20)
ax1.tick_params(axis = 'y', colors='w',size = 20)
#ax1.text()
#

ax2.axhline(100)
BundleFc_Outcome['ROAS'].plot(kind = 'bar',color = 'red',width = 0.4, ax = ax2,position = 0.25)
plt.grid()
#ax2.set_ylim(0, 4000)
ax2.set_ylim(0,300)
plt.title('ROAS & SPEND By Bundle FC',color = 'w',size= 20)
plt.legend([ax2,ax1],labels = ['SPEND','ROAS'],loc = 0)

The code gives me the following picture:

result of above code

After implementing the suggestion in the comments, the picture looks like this (does not solve the problem):

result after changing legend location


Solution

  • I don't recommend using the builtin functions of pandas to do more complex plotting. Also when asking a question it is common courtesy to provide a minimal and verifiable example (see here). I took the liberty to simulate your problem.

    Due to the change in axes, we need to generate our own legend. First the results:

    enter image description here

    Which can be achieved with:

    import matplotlib.pyplot as plt, pandas as pd, numpy as np
    # generate dummy data.
    X  = np.random.rand(10, 2)
    X[:,1] *= 1000
    x  = np.arange(X.shape[0]) * 2 # xticks
    df = pd.DataFrame(X, columns = 'Spend Roast'.split())
    # end dummy data
    
    fig, ax1 = plt.subplots(figsize = (9,6),sharex=True)
    ax2 = ax1.twinx()
    
    # tmp axes
    axes = [ax1, ax2] # setup axes
    colors = plt.cm.tab20(x)
    width = .5 # bar width
    
    # generate dummy legend
    elements = []
    # plot data
    for idx, col in enumerate(df.columns):
        tax = axes[idx]
        tax.bar(x + idx * width, df[col], label = col, width = width, color = colors[idx])
        element = tax.Line2D([0], [0], color = colors[idx], label = col) # setup dummy label
        elements.append(element)
    # desired hline
    tax.axhline(200, color = 'red')
    tax.set(xlabel = 'Bundle FC', ylabel = 'ROAST')
    axes[0].set_ylabel('SPEND')
    tax.legend(handles = elements)