Интерактивный сюжет Covid с несколькими выпадающими списками iPyWidgets - PullRequest
0 голосов
/ 02 апреля 2020

Я пытаюсь собрать блокнот Jupyter, который позволяет пользователю вводить состояние в раскрывающемся списке, который изменит результат во втором раскрывающемся списке, чтобы показывать только города из этого состояния. После выбора города можно нажать кнопку, чтобы обновить sh график (я понимаю, что вы можете использовать руководство с интерактивом, но не смог заставить его функционировать должным образом) и показать результирующие данные (со временем случайные случаи) , У меня был некоторый успех в создании виджетов, но я не могу заставить данные правильно построить график.

Я впервые использую виджеты в Jupyter, и я немного растерялся из-за взаимодействия, интерактивности, отображать и наблюдать (не говоря уже об устаревшем on_trait_change). Вот что у меня пока ...

from ipywidgets import interact, widgets
from bqplot import pyplot as plt
import pandas as pd

#make example DF
date_list = ['2020-02-01','2020-02-01','2020-02-01','2020-02-01','2020-02-02','2020-02-02','2020-02-02','2020-02-02']
state_list = ['CA','NY','CA','NY','CA','NY','CA','NY']
city_list = ['San Fran','NYC','LA','Albany','San Fran','NYC','LA','Albany']
cases_list = [0,0,0,0,2,6,4,8]

df = pd.DataFrame(index=date_list)
df['state'] = state_list
df['city'] = city_list
df['cases'] = cases_list

#getting unique state and city list sorted in alphabetical order
state_unique = df['state'].unique()
state_unique.sort()

state = widgets.Dropdown(
    options=['All'] + list(state_unique),
    value='CA', #indicates default starting value
    description='State:', #this is the label for the dropdown
)

city = widgets.Dropdown(
    description='City:',
)


# function that updates 'city' dropdown depending on value in 'state' dropdown
def list_cities(x):
    if state.value == 'All':
        city.options = ['']
        return city_list
    else:
        temp = ['All'] + sorted(df.loc[df['state'].eq(state.value),'city'].unique())
        city.options = temp

state.observe(list_cities, names = 'value') #the names part tells the observe the change name to look for, this is only looking for value changes



b_refresh = widgets.Button(
    description='Refresh',
    icon='fa-refresh',
    button_style='warning',
    layout=widgets.Layout(width='100px')
)

# plotting function
def set_plot(x_data,y_data):
    plt.plot(x_data, y_data)
    plt.show()

x = list(df.index.unique())
y = df.loc[\
    (df['city']==city.value)&\
    (df['state']==state.value),'cases']

b_refresh.on_click(set_plot(x, y))

display (state,city,b_refresh)

1 Ответ

0 голосов
/ 21 апреля 2020
from ipywidgets.widgets import Dropdown, Button
from ipywidgets.widgets import Layout, HBox, VBox
import bqplot as bq
import pandas as pd

#make example DF
date_list = ['2020-02-01','2020-02-01','2020-02-01','2020-02-01','2020-02-07','2020-02-07','2020-02-07','2020-02-07']
state_list = ['CA','NY','CA','NY','CA','NY','CA','NY']
city_list = ['San Fran','NYC','LA','Albany','San Fran','NYC','LA','Albany']
cases_list = [0,10,0,12,2,6,4,8]

df = pd.DataFrame(index=date_list)
df['state'] = state_list
df['city'] = city_list
df['cases'] = cases_list

df.index = pd.to_datetime(df.index)
df.rename_axis("date", axis='index', inplace=True)

#getting unique state list sorted in alphabetical order
state_unique = df['state'].unique()
state_unique.sort()

#make graphical parts - 2 dropdowns and refresh button
state = Dropdown(
    options=['All'] + list(state_unique),
    value='All', #indicates default starting value
    description='State:', #this is the label for the dropdown
    layout=Layout(width='200px',
    margin = '0px 0px 0px 0px')
)

city = Dropdown(
    description='City:',
    layout=Layout(width='200px',
    margin = '0px 0px 0px 0px')
)

b_refresh = Button(
    description='Refresh',
    icon='fa-refresh',
    button_style='warning',
    layout=Layout(width='100px',
              margin = '0px 0px 0px 60px')
)

#make graph parts
x = list(df.index.unique())
y = list(df.groupby('date')['cases'].sum())

xs = bq.DateScale()
ys = bq.LinearScale(min=0)

line = bq.Lines(
    x=x, 
    y=y, 
    scales={'x': xs, 'y': ys}
    )

x_ax = bq.Axis(
    scale=xs, 
    label='Dates', 
    grid_lines='solid', 
    tick_format='%m-%d', 
    tick_rotate=-0, 
    label_location ='middle',
    label_offset = "40px"
)

y_ax = bq.Axis(
    scale=ys, 
    orientation='vertical', 
    tick_format=',d', 
    label='FillInLater', 
    grid_lines='solid',
    label_offset = "60px"
)

# function that updates 'city' dropdown depending on value in 'state' dropdown
def list_cities(x):
    if state.value == 'All':
        global y
        city.options = ['']
        y = list(df.groupby('date')['cases'].sum())
    else:
        temp = ['All'] + sorted(df.loc[df['state'].eq(state.value),'city'].unique())
        city.options = temp
        update_city(x)


# function that updates graph's y values depending on value in 'city' dropdown
def update_city(x):
    global y
    if city.value == 'All':
        matching_cities = df.loc[(df['state']==state.value),'cases'].to_frame(name='cases')
        y = list(matching_cities.groupby('date')['cases'].sum())       
    else:
        y = list(df.loc[\
        (df['city']==city.value)&\
        (df['state']==state.value),'cases'])

# update plot function
def set_plot(b):
    global y
    line.y = [y]


#assign widget actions to functions
state.observe(list_cities, names = 'value') #the names part tells .observe the change name to look for, this is only looking for value changes
city.observe(update_city, names = 'value')        
b_refresh.on_click(set_plot)

#display all
fig = bq.Figure(
    layout=Layout(width='95%', height='400px', border ='solid 1px gray'),
    axes=[x_ax, y_ax],
    marks=[line],
    fig_margin=dict(top=10, bottom=80, left=80, right=20),
    animation_duration=500
)

box = HBox(
    children=(state, city, b_refresh),
    layout=Layout(margin = '10px 0px 10px 0px')
)

vert_box  = VBox(
    children=(box, fig),
    layout=Layout(border='solid 1px gray', margin = '0 0 0 0')
)

display (vert_box)
...