Взаимодействие с несколькими виджетами Bokeh - PullRequest
0 голосов
/ 06 июня 2018

РЕДАКТИРОВАТЬ: Некоторые пользователи упоминали, что вопрос неясен.Моя цель - отслеживать предыдущие состояния.

Я пытаюсь создать график, который можно изменить с помощью 3 виджетов.Однако каждое новое изменение виджета не учитывает предыдущие выборы виджета (например, если выбор сделан с использованием виджета 1, а затем виджет 2 изменен, модификация виджета 2 учитывает исходный график, а не изменения, сделанные с помощью виджета 1).

Я стараюсь избегать использования Custom_JS, так как у меня нет опыта работы с Javascript.Есть ли способ объединить функции так, чтобы любое изменение в виджетах учитывало предыдущие взаимодействия виджетов?

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import matplotlib
from datetime import date


from ipywidgets import interact
from bokeh.io import push_notebook, show, output_notebook, curdoc
from bokeh.plotting import figure
from bokeh.layouts import column, layout, widgetbox, row

from bokeh.models import ColumnDataSource, HoverTool, CustomJS, Panel

from bokeh.layouts import widgetbox
from bokeh.models.widgets import RangeSlider, Slider, Select, 
DateRangeSlider, Tabs

df = pd.read_csv("/Users/danielmontillanavas/Desktop/Tiller/00_Data/SF_may_correct_decimal.csv", sep =',',decimal=',')
df = df.drop(['Unnamed: 0'], axis=1)


df.rename(columns = {'Stamped phone from HS':'phone','Contact Email':'Email','Account Name':'Account_name',
                   'Opportunity ID':'ID', 'Close Date':'Close_date','Stamped-date of closed (DO NOT USE)':'Stamped_date',
                   'Quote Amount':'Quote_Amount', 'Lead Source':'Source','Desired activation date':'Activ_date'},
     inplace=True)

df.Close_date = pd.to_datetime(df.Close_date, format='%Y-%m-%d')

cols_num = ['Quote_Amount','DISCOUNT']
df[cols_num] = df[cols_num].apply(pd.to_numeric)

df_closed = df[df['Stage']=='Closed']
df_closed.fillna("Unknown", inplace=True)
start_point = min(df['Quote_Amount'])
end_point = max(df['Quote_Amount'])

TOOLS = 'pan,wheel_zoom,box_zoom,reset,tap,save,box_select,lasso_select'

source = ColumnDataSource(df_closed)

hover = HoverTool(
    tooltips=[
        ("Quote", "$x"),
        ("Discount", "$y")
    ]
)

p = figure(title='Quotes per Source - Closed deals',tools=[hover,TOOLS],
       plot_height=800, plot_width=800)

p.circle('Quote_Amount','DISCOUNT',source=source, size = 8, color = 'CornflowerBlue', alpha = 0.6)

N = 20000
slider = Slider(start=start_point, end=end_point, step=10, value=N, 
title='Select Quote Amount Cutoff')

dfList = df_closed.Source.unique().tolist()
All_view = ['All']
source_options = All_view + dfList
menu = Select(title = "Select Lead Source",options=source_options, value = 'All')

first_date = min(df['Close_date'])
last_date = max(df['Close_date'])

date_range_slider = DateRangeSlider(title="Select Date Range ", start=first_date, end=date.today(), value=(date(2017, 9, 7), date(2017, 10, 15)), step=1)

def slider_callback(attr, old, new):
  N = new  # this works also with slider.value but new is more explicit
  new1 = ColumnDataSource(df_closed.loc[(df_closed.Quote_Amount < N)])
  source.data = new1.data
  slider.on_change('value',slider_callback)

def menu_callback(attr, old, new):
  if menu.value == 'All': new2 = ColumnDataSource(df_closed)
  else: new2 = ColumnDataSource(df_closed.loc[(df_closed.Source == menu.value)])
  source.data = new2.data
menu.on_change('value',menu_callback)

def date_callback(attr, old, new):
  start = date_range_slider.value_as_datetime[0].strftime("%Y-%m-%d")
  end = date_range_slider.value_as_datetime[1].strftime("%Y-%m-%d")
  df_closed_new = df_closed[df_closed['Close_date'] >= start]
  df_closed_new = df_closed[df_closed['Close_date'] <= end]
  new3 = ColumnDataSource(df_closed_new)
  source.data = new3.data
date_range_slider.on_change('value',date_callback)

# Put controls in a single element
controls = widgetbox(menu, slider, date_range_slider)

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

curdoc().add_root(layout)

1 Ответ

0 голосов
/ 06 июня 2018

Ваш вопрос мне не очень понятен.Вы говорите о предыдущем состоянии виджетов?Обратные вызовы имеют доступ к текущему состоянию всех остальных виджетов *1001*, поэтому, если вы хотите сохранить историю их предыдущих состояний, вам придется явно отслеживать это.

Однако я сразу замечаю, что не следует делать, поэтому собираюсь опубликовать ответ, просто чтобы привлечь к нему внимание.Не создавайте новые объекты CDS только для того, чтобы использовать их атрибут .data и выбрасывать их:

new1 = ColumnDataSource(df_closed.loc[(df_closed.Quote_Amount < N)])
source.data = new1.data

Под крышками находится много механизмов, которые обеспечивают всю автоматическую синхронизацию с другимиособенности боке.CDS, в частности, являются чрезвычайно тяжелыми и сложными объектами, и выполнение вышеупомянутых действий является известным анти-паттерном, который может сломать вещи.Вместо этого, если вам просто нужен новый подходящий .data dict, используйте from_df:

new_data = ColumnDataSource.from_df(df_closed.loc[(df_closed.Quote_Amount < N)])

source.data = new_data
...