Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DropDown not working with Bokeh

I have a script to plot the prices of some share that the user wants to look at : he can choose the shares via a Dropdown button and Bokeh will draw the curve accordingly. (I am working in jupyter notebook) :

from bokeh.io import output_notebook, show
from bokeh.plotting import figure
output_notebook()

my code is the following :

from bokeh.models import  Callback, ColumnDataSource, Select,CustomJS
from bokeh.plotting import figure, show, gridplot
from bokeh.models.widgets.layouts import VBox
import pandas as pd

shares = ['AAPL', 'MSFT', 'IBM', 'All']

AAPL = pd.read_csv("http://ichart.yahoo.com/table.csv?s=AAPL&a=0&b=1&c=2000&d=0&e=1&f=2015",parse_dates=['Date'])
MSFT = pd.read_csv("http://ichart.yahoo.com/table.csv?s=MSFT&a=0&b=1&c=2000&d=0&e=1&f=2015",parse_dates=['Date'])
IBM = pd.read_csv("http://ichart.yahoo.com/table.csv?s=IBM&a=0&b=1&c=2000&d=0&e=1&f=2015",parse_dates=['Date'])

max_price = max(AAPL['Adj Close'].max(), MSFT['Adj Close'].max(), IBM['Adj Close'].max()) + 10
min_date = min(AAPL['Date'].min(), MSFT['Date'].min(), IBM['Date'].min())
max_date = max(AAPL['Date'].max(), MSFT['Date'].max(), IBM['Date'].max())

myplot = figure(title="Share price", x_axis_type="datetime", x_range=[min_date,max_date],y_range=[0,max_price],
        background_fill='#FFF5EE', plot_width=900, plot_height = 400, outline_line_color= None)

source_AAPL = ColumnDataSource(data=dict(x=AAPL['Date'], y = AAPL['Adj Close'], ytemp = AAPL['Adj Close']))
source_MSFT = ColumnDataSource(data=dict(x=MSFT['Date'], y = MSFT['Adj Close'], ytemp = MSFT['Adj Close']))
source_IBM  = ColumnDataSource(data=dict(x=IBM['Date'],  y = IBM['Adj Close'],  ytemp = IBM['Adj Close']))

myplot.line(x ='x', y ='y', color='#A6CEE3', source = source_AAPL, name='AAPL')
myplot.line(x ='x', y ='y', color='#33A02C', source = source_MSFT, name='IBM')
myplot.line(x ='x', y ='y', color='#FB9A99', source = source_IBM, name='MSFT') 


Callback_Shares = CustomJS(args={'source_AAPL': source_AAPL,'source_MSFT': source_MSFT,'source_IBM': source_IBM}, code="""
    var f = cb_obj.get('value');
    var data_AAPL = source_AAPL.get('data');
    var data_MSFT = source_MSFT.get('data');     
    var data_IBM = source_IBM.get('data');
    if (f == 'AAPL') {
        data_MSFT['y'] = [0 for i in range(len(data_MSFT['x']))];
        data_IBM['y'] = [0 for i in range(len(data_IBM['x']))];
        data_AAPL['y'] = data_AAPL['ytemp'] ;
        source_AAPL.trigger('change');
        source_MSFT.trigger('change');
        source_IBM.trigger('change');
        }
    if (f == 'MSFT') {
        data_AAPL['y'] = [0 for i in range(len(data_AAPL['x']))];
        data_IBM['y'] = [0 for i in range(len(data_IBM['x']))];
        data_MSFT['y'] = data_MSFT['ytemp'] ;
        source_AAPL.trigger('change');
        source_MSFT.trigger('change');
        source_IBM.trigger('change');
        }
    if (f == 'IBM') {
        data_AAPL['y'] = [0 for i in range(len(data_AAPL['x']))];
        data_MSFT['y'] = [0 for i in range(len(data_MSFT['x']))];
        data_IBM['y'] = data_IBM['ytemp'] ;
        source_AAPL.trigger('change');
        source_MSFT.trigger('change');
        source_IBM.trigger('change');
        }
    if (f == 'All') {
        data_AAPL['y'] = data_AAPL['ytemp'];
        data_MSFT['y'] = data_MSFT['ytemp'];
        data_IBM['y'] = data_IBM['ytemp'];
        source_AAPL.trigger('change');
        source_MSFT.trigger('change');
        source_IBM.trigger('change');
        }"""
)

dropdown = Select(title="Shares:", value=shares[3], options=shares, callback = Callback_Shares)

myfigure =  VBox(dropdown, gridplot([[myplot]]))
show(myfigure)

My problem is the figure always shows the 3 curves and does not take into account the choice of the DropDown...

like image 205
eleanor Avatar asked Mar 10 '23 07:03

eleanor


1 Answers

The other answer is unfortunately not an optimal one. As a project maintainer I feel obligated to show the project in the best light. Here is a much simpler complete example that functions the same and works with Bokeh 0.12.4:

from bokeh.models import CustomJS, ColumnDataSource, Select
from bokeh.plotting import figure, output_file, show
from bokeh.layouts import column
import pandas as pd

url = "http://ichart.yahoo.com/table.csv?s=%s&a=0&b=1&c=2000&d=0&e=1&f=2015"

AAPL = pd.read_csv(url % "AAPL", parse_dates=['Date'])
MSFT = pd.read_csv(url % "MSFT", parse_dates=['Date'])
IBM  = pd.read_csv(url % "IBM",  parse_dates=['Date'])

max_price = max(AAPL['Close'].max(), MSFT['Close'].max(), IBM['Close'].max())

source = ColumnDataSource({
    'xAAPL' : AAPL['Date'], 'yAAPL' : AAPL['Close'], 'yAAPLp' : AAPL['Close'],
    'xMSFT' : MSFT['Date'], 'yMSFT' : MSFT['Close'], 'yMSFTp' : MSFT['Close'],
    'xIBM'  :  IBM['Date'], 'yIBM'  :  IBM['Close'], 'yIBMp'  :  IBM['Close']
})

p = figure(width=500, height=250, x_axis_type="datetime", y_range=[0, max_price+10])

r_aapl = p.line('xAAPL', 'yAAPL', source=source, color='navy',  alpha=0.5)
r_msft = p.line('xMSFT', 'yMSFT', source=source, color='red',   alpha=0.5)
r_ibm  = p.line('xIBM',  'yIBM',  source=source, color='green', alpha=0.5)

callback = CustomJS(args=dict(r_aapl=r_aapl, r_msft=r_msft, r_ibm=r_ibm), code="""
    f = cb_obj.value;
    r_aapl.visible = false;
    r_msft.visible = false;
    r_ibm.visible = false;
    if      (f == "AAPL") { r_aapl.visible = true; }
    else if (f == "MSFT") { r_msft.visible = true; }
    else if (f == "IBM")  { r_ibm.visible = true; }
    else {
        r_aapl.visible = true;
        r_msft.visible = true;
        r_ibm.visible = true;
    }
""")

shares = ['AAPL', 'MSFT', 'IBM', 'All']
multi_select = Select(title="Select Shares:", value=shares[3], options=shares, callback=callback)

output_file("datetime.html")

show(column(multi_select, p))

enter image description here

enter image description here

I should also add, "interactive legends" that allow glyphs to be hidden or muted by clicking on the legend, will be added as as standard feature in 0.12.5.

like image 115
bigreddot Avatar answered Mar 31 '23 12:03

bigreddot