我试图嵌入我的阴谋。我有选择小部件的x轴和y轴选择。当我改变y轴时,情节会按预期更新(图1);然而,改变x轴给我带来了问题。 在更改x轴选项后,新线图将叠加在旧图形的顶部(图2)。只有当我刷新页面时,图形才会按预期呈现(图3)。如何在不刷新整个页面的情况下刷新绘图?
这是我正在尝试的实例:
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()
答案 0 :(得分:2)
您应该使用source.data.update(dict)更新行的来源,而不是使用p.line()重新绘制行。只需要一个空的源来在开头绘制线而没有数据。
更新图形范围后也更新源
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())
))