2016-12-23 5 views
2

У меня есть сценарий для расчета цен на какую-то долю, на которую пользователь хочет посмотреть: он может выбрать акции с помощью кнопки Dropdown, и Bokeh будет рисовать кривую соответственно. (я работаю в jupyter ноутбук):DropDown не работает с Bokeh

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

мой код выглядит следующим образом:

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) 

Моя проблема фигура всегда показывает 3 кривые и не принимает во внимание выбор DropDown ...

ответ

5

Другого ответа, к сожалению, не является оптимальным. Как руководитель проекта, я чувствую себя обязанным показать проект в лучшем свете. Здесь гораздо проще полный пример, который действует так же и работает с 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

Я должен также добавить, «интерактивные легенды», которые позволяют глифы быть скрыты или приглушенный щелчком по легенде, будет добавлен как стандартная функция в 0.12.5.

+0

Это решение не работает для меня, у меня такая же проблема: я всегда вижу 3 кривые. Я работаю над ноутбуком Jupyter, а моя версия Bokeh - 0.12.0 – eleanor

+0

Как я уже говорил, это решение для '0.12.4' (возможно, оно будет работать и для версии или двух ранее). Вы никогда ранее не заявляли версию, которую вы использовали. Новые функции и возможности добавляются последовательно, а «0.12.0» - год. Если вам нужен ответ, специфичный для конкретной версии (т. Е. Вы используете годовую версию быстродвижущегося проекта), это * важная информация *, чтобы предоставить людям, которые пытаются вам помочь. – bigreddot

+0

действительно я должен был упомянуть об этом раньше! Я обновил bokeh, чтобы иметь 0.12.4, но теперь я не вижу графики, у меня есть только выпадающее меню. Я использую python 2.7 и pandas 0.18.1. (У меня также есть будущее 0.16.0) – eleanor

0

Вместо того, чтобы обновлять фактические источники данных, есть намного более простые способы контроля видимости. Вы можете установить альфа альфа на нуль или цвет на None или, возможно, наиболее непосредственно, установите для свойства visible объекта рендера False, как видно из this example. Соответствующая часть этого примера, упрощенных некоторые, этот код:

r0 = p.line(x, y0, color="red") 
r1 = p.line(x, y1, color="green") 
r2 = p.line(x, y2, color="blue") 

checkbox = CheckboxGroup(labels=["Line 0", "Line 1", "Line 2"], 
         active=[0, 1, 2], width=100) 

checkbox.callback = CustomJS.from_coffeescript(
    args=dict(r0=r0, r1=r1, r2=r2, checkbox=checkbox), 
    code=""" 
r0.visible = 0 in checkbox.active; 
r1.visible = 1 in checkbox.active; 
r2.visible = 2 in checkbox.active; 
""") 
+0

установка опции графа для p1.visible = False не работает – eleanor

+0

Вы говорите, что полный связанный пример не работает для вас? Также не уверен, что такое 'p1', или если это правильно, это не в вашем исходном коде. – bigreddot

+0

пример не работает: сначала мне пришлось изменить «CustomJS.from_coffeescript» для «CustomJS» (AttributeError: type object 'CustomJS' не имеет атрибута 'from_coffeescript'), тогда, когда я нажимаю на квадраты, ничего не происходит – eleanor

0

я нашел следующее решение после некоторой работы:

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

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['Close'].max(), MSFT['Close'].max(), IBM['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()) 

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

p = figure(width=500, height=250, x_axis_type="datetime", x_range=[min_date,max_date],y_range=[0,max_price]) 

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

callback = CustomJS(args=dict(source=source), code=""" 
    var data = source.get('data'); 
    var f = cb_obj.get('value') 
    yAAPL = data['yAAPL'] 
    yMSFT = data['yMSFT'] 
    yIBM = data['yIBM'] 
    yAAPLp = data['yAAPLp'] 
    yMSFTp = data['yMSFTp'] 
    yIBMp = data['yIBMp'] 
    if (f == "AAPL") { 
     for (i = 0; i < yAAPL.length; i++) {yAAPL[i] = yAAPLp[i]}    
     for (i = 0; i < yMSFT.length; i++) {yMSFT[i] = 'nan'} 
     for (i = 0; i < yIBM.length; i++) {yIBM[i] = 'nan'} 
    } 
    else if (f == "MSFT") { 
     for (i = 0; i < yAAPL.length; i++) {yAAPL[i] = 'nan'}    
     for (i = 0; i < yMSFT.length; i++) {yMSFT[i] = yMSFTp[i]} 
     for (i = 0; i < yIBM.length; i++) {yIBM[i] = 'nan'} 
    } 
    else if (f == "IBM") { 
     for (i = 0; i < yAAPL.length; i++) {yAAPL[i] = 'nan'}    
     for (i = 0; i < yMSFT.length; i++) {yMSFT[i] = 'nan'} 
     for (i = 0; i < yIBM.length; i++) {yIBM[i] = yIBMp[i]} 
    } 
    else { 
     for (i = 0; i < yAAPL.length; i++) {yAAPL[i] = yAAPLp[i]}    
     for (i = 0; i < yMSFT.length; i++) {yMSFT[i] = yMSFTp[i]} 
     for (i = 0; i < yIBM.length; i++) {yIBM[i] = yIBMp[i]} 
    } 
    source.trigger('change'); 
""") 

shares = ['AAPL', 'MSFT', 'IBM', 'All'] 
multi_select = Select(title="Select Shares:", value=shares[3],  options=shares, callback=callback) 
layout = VBox(multi_select, p) 
show(layout) 
Смежные вопросы