График Bokeh не обновляется при использовании CheckBoxGroup - PullRequest
0 голосов
/ 18 апреля 2020

Я занимаюсь этим часами. Я пытаюсь представить график распространения (и смертей) Covid-19 в разных странах мира (он показывает новые случаи, общее количество случаев, новые случаи смерти и общее количество смертей в разных таблицах). Я хочу позволить пользователю выбирать, какие страны он хочет видеть, используя виджет CheckBoxGroup из Bokeh, но мой график не обновляется. Кроме того, при отладке я заметил, что функция обновления обновляется только тогда, когда есть новый выбор (или так кажется). Когда я выбираю страну, если я печатаю данные sr c из функции обновления, данные из новой страны присутствуют (но не отображаются на графике). Однако, когда я отменяю выбор страны, данные из этой страны все еще присутствуют после того, как они должны были быть обновлены.

Я не знаю, создает ли проблема использование groupby (я не видел никаких рабочих примеров с groupby, я пытался использовать MultiLine, но я не совсем уверен, что понял цель).

PS: Если кто-нибудь знает, как отформатировать CheckBoxGroup, чтобы иметь столбцы, это также было бы здорово, но сейчас это далеко не приоритет.

Заранее спасибо!

import pandas as pd
import numpy as np
import datetime as dt
from os.path import dirname, join


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

from bokeh.models import CategoricalColorMapper, HoverTool, ColumnDataSource, Panel,CustomJS
from bokeh.models.widgets import CheckboxGroup, Slider, RangeSlider, Tabs, MultiSelect

from bokeh.layouts import column, row, WidgetBox
from bokeh.palettes import all_palettes

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





def make_dataset(select_countries):
    prep_data={}
    for i,group in enumerate(select_countries):
        group[1].set_index('date', drop=True, inplace=True)
        data=group[1].reindex(all_days)
        data["location"].fillna(method='backfill',inplace=True)
        data.fillna(value=0,inplace=True)
        data['color']=color_list[i]
        data.reset_index(inplace=True)
        prep_data[group[0]]=data
    return ColumnDataSource(prep_data)

def make_plot(src):

    p1 = figure(plot_width=1000, plot_height=600,x_axis_type='datetime',title = 'Chart of new cases over time',
              x_axis_label = 'Date', y_axis_label = 'Number of new cases')
    p2 = figure(plot_width=1000, plot_height=600,x_axis_type='datetime',title = 'Chart of total cases over time',
              x_axis_label = 'Date', y_axis_label = 'Number of total cases')
    p3 = figure(plot_width=1000, plot_height=600,x_axis_type='datetime',title = 'Chart of new deaths over time',
              x_axis_label = 'Date', y_axis_label = 'Number of new deaths')
    p4 = figure(plot_width=1000, plot_height=600,x_axis_type='datetime',title = 'Chart of total deaths over time',
              x_axis_label = 'Date', y_axis_label = 'Number of total deaths')
    for group in src.data.values() :
        plot1=p1.line(x='index',y='new_cases',source=group,color=group['color'].values[0],legend="location")
        plot2=p2.line(x='index',y='total_cases',source=group,color=group['color'].values[0],legend="location")
        plot3=p3.line(x='index',y='new_deaths',source=group,color=group['color'].values[0],legend="location")
        plot4=p4.line(x='index',y='total_deaths',source=group,color=group['color'].values[0],legend="location")

    p1.legend.click_policy = 'hide'
    p2.legend.click_policy = 'hide'
    p3.legend.click_policy = 'hide'
    p4.legend.click_policy = 'hide' 

    tab1 = Panel(child=p1, title="new_cases")
    tab2 = Panel(child=p2, title="total_cases")
    tab3 = Panel(child=p3, title="new_deaths")
    tab4 = Panel(child=p4, title="total_deaths")


    tabs = Tabs(tabs=[ tab1, tab2, tab3, tab4 ])


    return tabs

def update(attr, old, new):
    # Get the list of countries
    select_countries_labels=[country_selection.labels[i] for i in country_selection.active]
    #print(select_countries_labels)
    select_countries=[countries_selected for countries_selected in countries
                  if countries_selected[0] in select_countries_labels]

    new_src = make_dataset(select_countries)
    #print("new countries")
    #print(new_country_list.data)
    # Update the source used the quad glpyhs
    src.data.update(new_src.data)
    #=new_country_list.data
    #print(country_df.data)


df=pd.read_csv(join(dirname(__file__),'full_data(2).csv'), encoding='utf-8',parse_dates=["date"])
countries=df.groupby("location")
l=countries.describe(include="all")
all_days=pd.date_range(l.loc['World']['date']['first'],l.loc['World']['date']['last'],freq='D')

# Countries and colors

color_dicts=[list(colors.values()) for colors in list(all_palettes.values())]
color_list_int=[color for color_sublist in color_dicts for color in color_sublist]
color_list_dup=[color for color_sublist in color_list_int for color in color_sublist]
color_list=list(set(color_list_dup))
color_list.sort()

available_countries = list(set(df['location']))
available_countries.sort()


# Countries to plot
country_selection = CheckboxGroup(labels=available_countries, 
                                  active = [0,1])
country_selection.on_change('active', update)

# Initial carriers and data source

select_countries_labels=[country_selection.labels[i] for i in country_selection.active]
initial_countries=[countries_selected for countries_selected in countries
                  if countries_selected[0] in select_countries_labels]

# Prep the data
src = make_dataset(initial_countries)

# Make the covid plot
p1 = make_plot(src)

# Put controls in a single element
controls = WidgetBox(country_selection)

# Create a row layout
layout = row(controls, p1)


curdoc().add_root(layout)
curdoc().title = "covid"
...