pottolom pottolom - 4 days ago 4
Python Question

Python Bokeh additional Y axis problems

I have written the code below to produce a line graph based on data from a Pandas dataframe. The index of the dataframe is a time series.

The code below was working well, but I decided I wanted to add one more data series (from the third column in my dataframe, referred to as 'Col3' in the code). I wanted this third series to be on a separate Y axis. However, when I added the code to achieve this, shown below highlighted by the ***, Bokeh seems unable to produce a plot. Does anyone have any idea what I am doing wrong?

from bokeh.plotting import figure, output_file, show, save
from bokeh.models import ColumnDataSource
from bokeh.models import Range1d, LinearAxis
import pandas as pd
from pandas import HDFStore
from bokeh.palettes import Spectral11

store = pd.HDFStore(<dataframe location>)
df = pd.DataFrame(store['d1'])
df = df.rename_axis('Time')
df.fillna(0)

numlines = len(df.columns)

#import colour pallete
mypalette = Spectral11[0:numlines]

# remove unwanted columns
col_list = ['Col1', 'Col2', 'Col3']
df = df[col_list]

# make a list of our columns
col = []
[col.append(i) for i in df.columns]

# make the figure,
p = figure(x_axis_type="datetime", title="<Plot Title>", width = 800, height = 450)
p.xaxis.axis_label = 'Date'
p.yaxis.axis_label = '<Name of Primary Y Axis>'

*** # add extra y axis
p.extra_y_ranges = {'Col3': Range1d(start=0, end=0.25)}
p.add_layout(LinearAxis(y_range_name='Performance ratio %'), 'right') ***

# loop through our columns and colors
for (columnnames, colore) in zip(col, mypalette):
p.line(df.index, df[columnnames], legend = columnnames, color = colore )

# creates an output file
output_file('<outputlocation>')

#save the plot
save(p)


For reference, my dataframe looks like this:

Dataframe looks like this:

Time Col1 Col2 Col3 Col4
29/11/2016 00:00 4 41 41 55
29/11/2016 01:00 55 15 61 81
29/11/2016 02:00 51 75 2 4
29/11/2016 03:00 21 21 51 9
etc.

Answer

A few issues:

When you do this:

p.extra_y_ranges = {'Col3': Range1d(start=0, end=0.25)}
p.add_layout(LinearAxis(y_range_name='Performance ratio %'), 'right')

You're creating another y_range named Col3 on the first line. You need to use this name on the second line, not Performance ratio %. (Or better yet, name it Performance ratio % on the first line too).

Also, in your loop you place all the 3 series on the same y axis, you need to specify y_range_name='Col3' for the third.

The following works:

numlines = len(df.columns)

#import colour pallete
mypalette = Spectral11[0:numlines]

# remove unwanted columns
col_list = ['Col1', 'Col2', 'Col3']
df = df[col_list]

# make the figure, 
p = figure(x_axis_type="datetime", title="<Plot Title>", 
           width = 800, height = 450, y_range=(0,100))
p.xaxis.axis_label = 'Date'
p.yaxis.axis_label = '<Name of Primary Y Axis>'


p.line(df.index, df['Col1'], legend = 'Col1', color = mypalette[0] )
p.line(df.index, df['Col2'], legend = 'Col2', color = mypalette[1] )

# add extra y axis
p.extra_y_ranges = {'Performance ratio %': Range1d(start=0, end=50)}
p.line(df.index, df['Col3'], legend = 'Col3', color = mypalette[2], 
         y_range_name='Performance ratio %' )
p.add_layout(LinearAxis(y_range_name='Performance ratio %'), 'right')

# creates an output file 
output_file('bokeh.html')

#save the plot
show(p)
Comments