0
votes

I would love some help, I'm going in circles here. I know I'm doing something stupid but my plot isn't updating. I can't debug to see if my filter function isn't working or there's a problem that my inputs for the plot aren't linked the dynamic source input. Since even the starting plot doesn't take the initialized parameters I think it's something there. PS- any advice on having a select all, including all in the categorical choices for the select boxes would be amazing too.

Cheers, Tom

import pandas as pd
import numpy as np

from bokeh.io import show, output_notebook, push_notebook, curdoc
from bokeh.plotting import figure

from bokeh.models import CategoricalColorMapper, HoverTool, ColumnDataSource, Panel, Div
from bokeh.models.widgets import (CheckboxGroup, Slider, Select, TextInput, RangeSlider, Tabs, CheckboxButtonGroup, TableColumn, DataTable, Select)

from bokeh.layouts import layout, column, row, Widgetbox
from bokeh.layouts import widgetbox, row, column
from bokeh.palettes import Category20_16

from bokeh.application.handlers import FunctionHandler
from bokeh.application import Application

weather = pd.read_csv('YYYYYY.csv', dayfirst=True, parse_dates=True, index_col=[1], encoding = "ISO-8859-1")

def style(p):
    # Title 
    p.title.align = 'center'
    p.title.text_font_size = '20pt'
    p.title.text_font = 'serif'

    # Axis titles
    p.xaxis.axis_label_text_font_size = '14pt'
    p.xaxis.axis_label_text_font_style = 'bold'
    p.yaxis.axis_label_text_font_size = '14pt'
    p.yaxis.axis_label_text_font_style = 'bold'

    # Tick labels
    p.xaxis.major_label_text_font_size = '12pt'
    p.yaxis.major_label_text_font_size = '12pt'

    return p    

def make_plot(src):
    p = figure(plot_height=600, plot_width=700, title="'2018'", toolbar_location="below", tooltips=TOOLTIPS)
    p.circle(x="Deal_Number", y="USD_Base", source=src, size=7, line_color=None)
    p = style(p)
    return p

TOOLTIPS=[
    ("Name", "@Target"),
    ("$", "@Round"),
    ("Country", "@CC")
]

def get_dataset(deal_num, ccstring, descstring, vertstring):
    df_filter = weather[weather['USD_Base'] >=(deal_num) & weather['CC'].str.contains(ccstring) & weather['Description'].str.contains(descstring) & weather['Vertical Market'].str.contains(vertstring)]
    return ColumnDataSource(df_filter)


def update_plot(attr, old, new):
    deal_num = int(deal_select.value)
    ccstring = str(cc_select.value)
    descstring = str(description_select.value)
    vertstring = str(vert_select.value)
    new_src = get_dataset(deal_num, ccstring, descstring, vertstring)
    src.data.update(new_src.data)

# Create Input controls
deal_select = Slider(title="$ Invested", value=0, start=0, end=200, step=2)
cclist = weather["CC"].unique().tolist()
cc_select = Select(title="Country Name:", options= cclist, value='GB')
description_select = TextInput(title="Company description contains")
vertlist = weather["Vertical Market"].unique().tolist()
vert_select = Select(title="Vertical:", options= ['All'] + vertlist, value='None')


controls = widgetbox(deal_select, cc_select, description_select, vert_select)

deal_select.on_change('value', update_plot) 
cc_select.on_change('value',update_plot)
description_select.on_change('value',update_plot)
vert_select.on_change('value',update_plot)

# Make the deal data source

src = get_dataset(deal_num = deal_select.value, 
            ccstring = cc_select.value, 
            descstring = description_select.value, 
            vertstring = vert_select.value)

# Make the deal plot
p = make_plot(src)

layout = row(controls, p)

# Make a tab with the layout 
tab = Panel(child=layout, title = '2018')

# Put all the tabs into one application
tabs = Tabs(tabs = [tab])

# Put the tabs in the current document for display
curdoc().add_root(tabs)
1

1 Answers

0
votes

If you are updating a glyph, you need to change the datasource for that glyph directly. In your case, you should assign the circle glyph to a variable, such as:

circle = p.circle(x="Deal_Number", y="USD_Base", source=src, size=7, line_color=None)

Then in your update_plot(attr, old, new) function try this:

circle = p.select_one({'name':'circle'})

circle.data_source.data = new_src.data

For selecting all, possibly the MultiSelect Widget would work?