Emrah
Emrah

Reputation: 103

CheckBoxGroup updating problem of List items in Bokeh

Apologies for having a long post. I am working on a visualisation that represents weekly inventory values of different locations. I am able to hide some locations from the graph by clicking the legend, but the y axis don't update itself. That is why I tried to implement CheckBoxGroup to filter the graph's items. However, I can draw the graph, but whenever I deselect some items in CheckBoxGroup, the graph is not updating itself. You can find image of the output below. Any help would be useful.

P.S: In order to reproduce the output processing the data codes must be run at first then graph codes.

Thank you, E

Output: Output of the code

Data : link

Processing the data:


import pandas as pd
import numpy as np

dataset_inventory = pd.read_excel('weekly_inventory_data.xls')
df = dataset_inventory.copy()
df = df.fillna(0)
df = df.replace('-',0)

resource = "çÇğĞıİöÖşŞüÜ"
target = "cCgGiIoOsSuU"
translate = str.maketrans(resource,target)
df['Location']= df['Location'].str.translate(translate)
df.columns = [x.lower() if type(x)==str else x for x in df.columns]
df['location'] = [x.lower() for x in df['location']]

df1 = df.copy()
df2 =df.copy()
for column in df2:
    if type(column) == int: 
        df2[column] = [1 if x>0 else 0 for x in df2[column]]
    else:
        pass  

def table(df,info):
    pivot = df.groupby('location').sum().T
    pivot.columns.names = ['']
    pivot['total'] = pivot.sum(axis=1)
    pivot.reset_index(level=0, inplace=True)
    pivot.insert(loc=0, column='year', value=np.where(pivot['index'].apply(lambda x: x > 16), 2015, 2016))
    pivot.insert(loc=2, column='year_week', value=pivot['year'].astype(str) +'_'+ pivot['index'].astype(str))
    pivot.reset_index(inplace=True)
    pivot.rename(columns={'level_0' :'observation','index':'week'}, inplace=True)
    pivot['year_week'] = pd.Categorical(pivot.year_week, ordered=True)
    pivot['observation'] = [x+1 for x in pivot['observation']]
    pivot.rename(columns={'cayirova' :'cayirova_'+info, 'orhanli' :'orhanli_'+info,
                          'fason' :'fason_'+info, 'samandira' :'samandira_'+info,
                          'gebze' :'gebze_'+info, 'sultanbeyli' :'sultanbeyli_'+info,
                          'yenidogan' :'yenidogan_'+info, 'total' :'total_'+info
                         }, inplace=True)
    return pivot

input1='qty'
input2='wh'
df1 = table(df1,input1)
df2 = table(df2,input2)

pivot = pd.concat([df1, df2.drop(['observation','year','week','year_week'],axis =1)], axis=1, sort=False)
cols_to_order = ['observation', 'year','week','year_week','total_'+input1,'total_'+input2]
new_columns = cols_to_order + (sorted(pivot.columns.drop(cols_to_order).tolist()))
inventory_pivot = pivot[new_columns]
inventory_pivot = inventory_pivot.set_index('observation')
inventory_pivot.insert(loc=0, column='date', value=pd.to_datetime(inventory_pivot.year.astype(str), format='%Y') + \
             pd.to_timedelta(inventory_pivot.week.mul(7).astype(str) + ' days'))

Graphing:

import pandas as pd
from bokeh.plotting import figure, output_file, show

import pandas as pd
import numpy as np

from bokeh.io import output_file, output_notebook, push_notebook
from bokeh.plotting import figure, show
from bokeh.models import ColumnDataSource
from bokeh.layouts import row, column, gridplot
from bokeh.models.widgets import Tabs, Panel
from bokeh.models import HoverTool
from bokeh.models import ColumnDataSource
from bokeh.models import NumeralTickFormatter
from bokeh.models import DatetimeTickFormatter
from math import pi
from bokeh.models import Legend
from bokeh.layouts import column, row
from bokeh.models import Column
from bokeh.application.handlers import FunctionHandler
from bokeh.application import Application
from bokeh.models.widgets import CheckboxGroup


inventory = ColumnDataSource(inventory_pivot)


def modify(doc):
    def update(attr, old, new):

        items_to_plot = [item_selection.labels[i] for i in 
                                item_selection.active]   


    def graph(items):

        fig = figure(plot_width=850, plot_height=500, x_axis_type="datetime", toolbar_location=None)
        fig.title.text = 'Click on legend entries to hide the corresponding lines'
        colors = ['blue','green','purple','brown','black','orange','red','yellow']

        legend_it = []
        for idx,item in enumerate(items): 
            graph = fig.line(x='date', y =item+'_'+input1, 
                               source=inventory, 
                               line_width=3,
                               color = colors[idx])
            legend_it.append((item, [graph]))

        legend = Legend(items=legend_it, location=(10,130))
        legend.click_policy="hide"
        fig.add_layout(legend, 'right')
        fig.legend.border_line_width = 1
        fig.legend.border_line_color = "navy"
        fig.legend.border_line_alpha = 0.5


        fig.ygrid.visible = False
        fig.xgrid.visible = False
        fig.yaxis.formatter=NumeralTickFormatter(format=",")
        fig.xaxis.major_label_orientation = pi/3
        fig.y_range.start = 0
        fig.xaxis.formatter=DatetimeTickFormatter(   
                    months=["%B %Y"],
                    years=["%B %Y"],   )

        tooltips = [
                        ('YEAR','@year'),
                        ('WEEK','@week'),
                        ('QUANTITY','$y{,}')            
                       ]

        fig.add_tools(HoverTool(tooltips=tooltips))

        return fig

    items_list = ['total','yenidogan','cayirova','sultanbeyli','samandira','orhanli','gebze','fason']

    item_selection = CheckboxGroup(labels=items_list, 
                                active = [0, 1, 2, 3, 4, 5, 6, 7], width =100)
    item_selection.on_change('active', update)  

    controls = Column(item_selection)

    initial_list = [item_selection.labels[i] for i in item_selection.active]        

    fig = graph(initial_list)

    layout = row(controls, fig)

    doc.add_root(layout)


output_notebook()
handler = FunctionHandler(modify)
app = Application(handler)
show(app)

Upvotes: 1

Views: 143

Answers (1)

Eugene Pakhomov
Eugene Pakhomov

Reputation: 10652

You don't need the checkbox group. Just add fig.y_range.only_visible = True somewhere.

Upvotes: 1

Related Questions