2017-11-16 17 views
0

私はプロットを埋め込むようにしています。私はx軸とy軸の選択のためのSelectウィジェットを持っています。プロットはy軸を変更したときに期待どおりに更新されます(図1)。しかし、x軸を変更することは私に問題をもたらしています。 x軸オプションを変更すると、新しい折れ線グラフが古いグラフの上に重ねられます(図2)。ページをリフレッシュするときだけ、グラフは期待通りにレンダリングされます(図3)。ページ全体をリフレッシュせずにプロットを更新するにはどうすればよいですか?Bokeh:コールバック時に、新しいプロットが古いプロットの上にオーバーレイされます

これは私がしようとしています何の実施例である:

import io 
import pandas as pd 

from bokeh.plotting import figure 
from bokeh.layouts import row, column 
from bokeh.models import ColumnDataSource, Range1d 
from bokeh.models.widgets import Select 
from bokeh.client import push_session 
from bokeh.document import Document 
from bokeh.embed import server_session 

document = Document() 
session = push_session(document) 

trip_data = [{"trip": '1', "totalDistanceTravelled": "4.66", "totalTimeTaken": "765083", "time": "1504189219256", 
       "carRegNo": "ABC123", "driverName": "Anne"}, 
      {"trip": '2', "totalDistanceTravelled": "14.63", "totalTimeTaken": "1282369", "time": "1504189219256", 
       "carRegNo": "DEF345", "driverName": "Harry"}, 
      {"trip": '3', "totalDistanceTravelled": "3.66", "totalTimeTaken": "602713", "time": "1504189219256", 
       "carRegNo": "XYZ890", "driverName": "Ron"}, 
      {"trip": '4', "totalDistanceTravelled": "7.11", "totalTimeTaken": "2234282", "time": "1504189219256", 
       "carRegNo": "ABC123", "driverName": "Anne"}, 
      {"trip": '5', "totalDistanceTravelled": "14.14", "totalTimeTaken": "1282369", "time": "1504189219256", 
       "carRegNo": "DEF345", "driverName": "Harry"}, 
      {"trip": '6', "totalDistanceTravelled": "4.33", "totalTimeTaken": "748446", "time": "1504189219256", 
       "carRegNo": "DEF345", "driverName": "Harry"}, 
      {"trip": '7', "totalDistanceTravelled": "10.66", "totalTimeTaken": "960362", "time": "1504189219256", 
       "carRegNo": "XYZ890", "driverName": "Ron"}] 

df = pd.DataFrame(trip_data) 
drivers = df['driverName'].str.strip() 
vehicles = df['carRegNo'].str.strip() 
time_stamp = df['time'].astype(float) 
total_distance_travelled = df['totalDistanceTravelled'].astype(float) 
df['totalTimeTaken'] = df['totalTimeTaken'].astype(float) 
df['totalTimeTaken'] /= 1000 * 3600 

# Create Input controls 
x_axis = Select(title="X Axis", options=sorted(["Drivers", "Vehicle Reg. Number"]), value="Drivers") 
y_axis = Select(title="Y Axis", options=sorted(["Distance Travelled (kms)", "Time Taken (hours)"]), 
       value="Time Taken (hours)") 
source = ColumnDataSource(data=dict(x=[], y=[])) 
p = figure(x_range=[], y_range=Range1d(), plot_height=600, plot_width=700, title="") 

def update(): 
    print "UPDATE" 
    col_key_values = { 
     "Time Taken (hours)": 'totalTimeTaken', 
     "Distance Travelled (kms)": 'totalDistanceTravelled' 
    } 

    x_map = { 
     "Drivers": drivers, 
     "Vehicle Reg. Number": vehicles 
    } 

    x_name = x_map[x_axis.value] 
    x_y_values = {} 
    for x in x_name.unique(): 
     x_y_values[x] = round(df.loc[x_name == x, col_key_values[y_axis.value]].astype(float).sum(), 2) 
    source.data = dict(
     x=list(x_y_values.keys()), 
     y=list(x_y_values.values()) 
    ) 
    p.y_range.start = min(x_y_values.values())-1 
    p.y_range.end = max(x_y_values.values())+1 
    p.xaxis.axis_label = x_axis.value 
    p.yaxis.axis_label = y_axis.value 
    p.x_range.factors = list(x_y_values.keys()) 
    p.line(x="x", y="y", source=source) 
    print source.data 
    return p 

def on_x_change(attr, old, new): 
    global x_axis 
    x_axis.value = new 
    update() 


def on_y_change(attr, old, new): 
    global y_axis 
    y_axis.value = new 
    update() 


def create_layout(): 
    print 'CREATE LAYOUT' 
    x_axis.on_change('value', on_x_change) 
    y_axis.on_change('value', on_y_change) 
    controls = column(children=[x_axis, y_axis]) 
    layout = column(children=[controls, update()]) 
    return layout 


layout = create_layout() 

html = u""" 
<html> 
    <head></head> 
    <body> 
     %s 
    </body> 
</html> 
""" % server_session(layout, session_id=session.id, relative_urls=False) 

with io.open("sample.html", mode='w+', encoding='utf-8') as f: 
    f.write(html) 

print(__doc__) 

document.add_root(layout) 

if __name__ == "__main__": 
    print("\npress ctrl-C to exit") 
    session.loop_until_closed() 

添付ファイル: First plot

Second plot overlaid over first

Second plot after refreshing the webpage

答えて

2

代わりのp.lineでラインを再描画します( )あなたは単にsource.data.update(dict)で行のソースを更新する必要があります。最初の行をデータなしで描画するための空のソースがあるだけです。あなたは数字の範囲を更新した後

もソースを更新

p = figure(x_range=[], y_range=Range1d(), plot_height=600, plot_width=700, title="") 
source = ColumnDataSource(data={'x':[],'y':[]}) 
p.line(x="x", y="y", source=source) 

def update(): 
    print "UPDATE" 
    col_key_values = { 
     "Time Taken (hours)": 'totalTimeTaken', 
     "Distance Travelled (kms)": 'totalDistanceTravelled' 
    } 

    x_map = { 
     "Drivers": drivers, 
     "Vehicle Reg. Number": vehicles 
    } 

    x_name = x_map[x_axis.value] 
    x_y_values = {} 
    for x in x_name.unique(): 
     x_y_values[x] = round(df.loc[x_name == x, col_key_values[y_axis.value]].astype(float).sum(), 2) 
    p.y_range.start = min(x_y_values.values())-1 
    p.y_range.end = max(x_y_values.values())+1 
    p.xaxis.axis_label = x_axis.value 
    p.yaxis.axis_label = y_axis.value 
    p.x_range.factors = list(x_y_values.keys()) 
    source.data.update(dict(
     x=list(x_y_values.keys()), 
     y=list(x_y_values.values()) 
    )) 
関連する問題