简体   繁体   中英

Why my bokeh server app won't update the figure

here's my data : https://drive.google.com/drive/folders/1CabmdDQucaKW2XhBxQlXVNOSiNRtkMm-?usp=sharing i want to use the select to choose the stock i want to show;and slider to choose the year range i want to show; and checkboxgroup to choose the index i want to compare with. the problem is when i adjust the slider, the figure will update, but when i use the select and checkboxgroup, the figure won't update, what's the reason?

from bokeh.io import curdoc
from bokeh.layouts import column, row
from bokeh.models import ColumnDataSource, Slider, TextInput , Select , Div, CheckboxGroup
from bokeh.plotting import figure
import pandas as pd
import numpy as np

price=pd.read_excel('price.xlsx',index_col=0)
# input control

stock = Select(title='Stock',value='AAPL',options=[x for x in list(price.columns) if x not in ['S&P','DOW']])
yr_1 = Slider(title='Start year',value=2015,start=2000,end=2020,step=1)
yr_2 = Slider(title='End year',value=2020,start=2000,end=2020,step=1)
index = CheckboxGroup(labels=['S&P','DOW'],active=[0,1])

def get_data():
    compare_index = [index.labels[i] for i in index.active]
    stocks = stock.value
    start_year = str(yr_1.value)
    end_year = str(yr_2.value)

    select_list = []
    select_list.append(stocks)
    select_list.extend(compare_index)
    selected = price[select_list]
    selected = selected [start_year:end_year]
    for col in selected.columns:
        selected[col]=selected[col]/selected[col].dropna()[0]

    return ColumnDataSource(selected)

def make_plot(source):
    fig=figure(plot_height=600, plot_width=700, title="",sizing_mode="scale_both", x_axis_type="datetime")
    data_columns = list(source.data.keys())
    for data in data_columns[1:]:
        fig.line(x=data_columns[0],y=data,source=source,line_width=3, line_alpha=0.6, legend_label=data)
    return fig

def update(attrname, old, new):
    new_source = get_data()

    source.data.clear()
    source.data.update(new_source.data)


#get the initial value and plot
source = get_data()
plot = make_plot(source)

#control_update

stock.on_change('value', update)
yr_1.on_change('value', update)
yr_2.on_change('value', update)
index.on_change('active', update)


# Set up layouts and add to document
inputs = column(stock, yr_1, yr_2, index)

curdoc().add_root(row(inputs, plot, width=800))
curdoc().title = "Stocks"

You're creating a new ColumnDataSource for new data. That's not a good approach. Instead, create it once and then just assign its data as appropriate.

In your case, I would do it like this:

  1. Create ColumnDataSource just once, as described above
  2. Do not use .update on CDS, just reassign .data
  3. Create the legend manually
  4. For that one line that's susceptible to the select change choose a static x field and use it everywhere instead
  5. Change the first legend item's label when you change the select's value to instead of that x field it has the correct name

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM