7

I'm trying to plot a line plot over a bar plot using MatPlotLib. So far I have both the plots showing but I can't get a secondary y-axis with a different scale to work. When I try and put another one in it overwrites the original scale. My code is below

def hridef_base(x):
if x == 1:

    deltatlapexit = ExitSummary['Avg tLap'] - ExitSummary2['Avg tLap']

    plt.figure()
    index = (EntrySummary.index + 1)
    barwidth = 0.2

    plt.ylim(0.0, 65.0)
    plt.bar(index-barwidth, EntrySummary['Avg FRH'], barwidth, color='r', yerr=EntrySummary['FRH StDev'], ecolor='k', label='Entry')
    plt.bar(index, ApexSummary['Avg FRH'], barwidth, color='#4169E1', yerr=ApexSummary['FRH StDev'], ecolor='k', label='Apex')
    plt.bar(index+barwidth, ExitSummary['Avg FRH'], barwidth, color='#32CD32', yerr=ExitSummary['FRH StDev'], ecolor='k', label='Exit')

    plt.plot(index, deltatlapexit, color='k', label='Entry')

    plt.xlabel('Turn Number')
    plt.ylabel('Average FRideH')
    plt.title('Average FRideH for Baseline setup')
    plt.xticks(index)
    plt.legend()

else:
    print "Baseline FRideH Not Selected"

Any advice on the matter is appreciated but please talk me through what to do instead of posting links to sites. I need to understand why I'm not able to do this.

Thank-you in advance. Please comment if I've missed anything out.

UPDATE

Thanks to the comments below the graph now has two separate y-axis. How ever the y-label for the bar data has jumped to the right and if I try and plot the line y-label I get an Attribute error.

def hridef_base(x):
if x == 1:

    deltatlapexit = ExitSummary['Avg tLap'] - ExitSummary2['Avg tLap']

    fig, axis1 = subplots()
    index = (EntrySummary.index + 1)
    barwidth = 0.2

    axis1.ylim(0.0, 65.0)
    axis1.bar(index-barwidth, EntrySummary['Avg FRH'], barwidth, color='r', yerr=EntrySummary['FRH StDev'], ecolor='k', label='Entry')
    axis1.bar(index, ApexSummary['Avg FRH'], barwidth, color='#4169E1', yerr=ApexSummary['FRH StDev'], ecolor='k', label='Apex')
    axis1.bar(index+barwidth, ExitSummary['Avg FRH'], barwidth, color='#32CD32', yerr=ExitSummary['FRH StDev'], ecolor='k', label='Exit')

    axis2 = axis1.twinx()
    axis2.set_ylim(-10.0, 10.0)
    axis2.plot(index, deltatlapexit, color='k', label='tDelta')

    axis1.xlabel('Turn Number')
    axis1.ylabel('Average FRideH')
    axis2.set_ylabel('tDelta')
    axis1.title('Average FRideH for Baseline setup')
    axis1.xticks(index)
    axis1.legend()
    axis2.legend()

else:
    print "Baseline FRideH Not Selected"

I would insert an image but I need 10 rep points...

The error I receive is: NameError: global name 'subplots' is not defined

6
  • 1
    Have you tried using twiny? Because otherwise, I don't see how you can adjust the scale of the secondary y-axis (as you mention). Commented Sep 9, 2015 at 8:26
  • 1
    I've looked at twiny a lot but I'm struggling to insert it into my code. A few pointers if you have experience would be appreciated. Commented Sep 9, 2015 at 8:37
  • You should be using explicit axis for your plotting (see matplotlib.org/users/artists.html#figure-container). Using plt.ylabel will change the last axis object you were working on. If you use axis2.ylabel this will set the label on the second axis. it will help to specify an axis handle for the first graph using fig, axis1 = subplots() and then use axis1.bar to plot your barcharts. Commented Sep 9, 2015 at 9:33
  • am I replacing plt.figure() with fig, axis1 = subplots() ? Commented Sep 9, 2015 at 9:40
  • 1/ Have you tried moving the plt.ylabel before the call to twinx()? 2/ How are trying to set the y-label for the twin-plot? Commented Sep 9, 2015 at 10:21

2 Answers 2

13

I don't have your data, but using the barplot example from matplotlib, here's an example with a bar plot and a line plot overplotted, with independently scaled y-axes:

from matplotlib import pyplot as plt
import numpy as np

plt.figure()          
N = 5
menMeans = (20, 35, 30, 35, 27)
menStd = (2, 3, 4, 1, 2)
width = 0.35       # the width of the bars
womenMeans = (25, 32, 34, 20, 25)
womenStd = (3, 5, 2, 3, 3)    
ind = np.arange(N)
plt.ylim(0.0, 65.0)
plt.bar(ind, menMeans, width, color='r', yerr=menStd, label='Men means')
plt.bar(ind+width, womenMeans, width, color='y', yerr=womenStd, label='Women means')
plt.ylabel('Bar plot')      

x = np.linspace(0, N)
y = np.sin(x)
axes2 = plt.twinx()
axes2.plot(x, y, color='k', label='Sine')
axes2.set_ylim(-1, 1)
axes2.set_ylabel('Line plot')

plt.show()

enter image description here

Sign up to request clarification or add additional context in comments.

1 Comment

You are a gent and a scholar sir! It has now plotted however the ylabel has jumped from the left to the right. If you could check back in a second when I've updated the question perhaps you could solve the new error?
5

As a minimal example of what you need based on this,

import numpy as np
import matplotlib.pyplot as plt

#Setup dummy data
N = 10
ind = np.arange(N)
bars = np.random.randn(N)
t = np.arange(0.01, 10.0, 0.01)

#Plot graph with 2 y axes
fig, ax1 = plt.subplots()

#Plot bars
ax1.bar(ind, bars, alpha=0.3)
ax1.set_xlabel('$x$')

# Make the y-axis label and tick labels match the line color.
ax1.set_ylabel('bar', color='b')
[tl.set_color('b') for tl in ax1.get_yticklabels()]

#Set up ax2 to be the second y axis with x shared
ax2 = ax1.twinx()
#Plot a line
ax2.plot(t, np.sin(0.25*np.pi*t), 'r-')

# Make the y-axis label and tick labels match the line color.
ax2.set_ylabel('sin', color='r')
[tl.set_color('r') for tl in ax2.get_yticklabels()]

plt.show()

which gives, enter image description here

3 Comments

Thank-you very much! Combined with Evert I now have a working graph. The y-label is a bit problematic so once I've updated the question could you please advise?
Is it possible to add the legend to this sort of plot?
Hi @user5029763, you can simply register the plot and bars with label and then plot legend, e.g. ax1.bar(ind, bars, alpha=0.3, label="bar") ax2.plot(t, np.sin(0.25*np.pi*t), 'r-', label="line") ax1.legend(loc=2) ax2.legend(loc=4)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.