在 Bokeh (0.11) 服务器应用程序中 refresh/update 绘图的快速正确方法是什么?
What is a fast and proper way to refresh/update plots in Bokeh (0.11) server app?
我有一个散景 (v0.11) 服务应用程序,它使用来自数据框的 (x,y) 坐标生成散点图。我想添加交互,以便当用户选择图上的点或在文本框中输入以逗号分隔的点的名称(即 "p55, p1234")时,这些点将在散点图上变为红色。
我找到了一种方法来完成此操作(下面的策略 #3),但对于大型数据帧来说它非常慢。我认为有更好的方法。谁能帮我吗?我是否遗漏了一些明显的函数调用?
- 策略 1(100 个点 <1ms)钻取现有图的 ColumnDataSource 数据并尝试更改所选点。
- 策略 2(每 100 点约 70 毫秒)用新创建的 ColumnDataSource 覆盖图的现有 ColumnDataSource。
- 策略 3(每 100 点约 400 毫秒)是策略 2,然后重新创建
图.
代码存放在 pastebin 上:http://pastebin.com/JvQ1UpzY最相关的部分复制如下。
def refresh_graph(self, selected_points=None, old_idxs=None, new_idxs=None):
# Strategy 1: Cherry pick current plot's source.
# Compute time for 100 points: < 1ms.
if self.strategy == 1:
t1 = datetime.now()
for idx in old_idxs:
self.graph_plot.data_source.data['color'][idx] = 'steelblue'
for idx in new_idxs:
self.graph_plot.data_source.data['color'][idx] = 'red'
print('Strategy #1 completed in {}'.format(datetime.now() - t1))
else:
t3 = datetime.now()
self.coords['color'] = 'steelblue'
self.coords.loc[selected_points, 'color'] = 'red'
new_source = bkmodels.ColumnDataSource(self.coords)
self.graph_plot = self.graph_fig.scatter('x', 'y', source=new_source, color='color', alpha=0.6)
print('Strategy #3 completed in {}'.format(datetime.now() - t3))
return
理想情况下,我希望能够使用策略#1,但它似乎不允许点在客户端浏览器中刷新。
感谢您的帮助!
仅供参考:我正在使用 RHEL 6.X
如果你是流数据,那么这里有一个相关的答案:Timeseries streaming in bokeh
如果您需要一次更新所有内容,那么您可以这样做,我的建议是您的策略 1,它已被证明,例如这里:
https://github.com/bokeh/bokeh/blob/master/examples/app/sliders.py
需要特别注意的是,您确实必须一次性更新所有 source.data
。其中一个假设是列数据源的所有列始终具有相同的长度。更新单个列存在打破此假设的风险,这可能会导致问题。所以您想一次更新所有内容,例如:
# Generate the new curve
x = np.linspace(0, 4*np.pi, N)
y = a*np.sin(k*x + w) + b
source.data = dict(x=x, y=y)
我有一个散景 (v0.11) 服务应用程序,它使用来自数据框的 (x,y) 坐标生成散点图。我想添加交互,以便当用户选择图上的点或在文本框中输入以逗号分隔的点的名称(即 "p55, p1234")时,这些点将在散点图上变为红色。
我找到了一种方法来完成此操作(下面的策略 #3),但对于大型数据帧来说它非常慢。我认为有更好的方法。谁能帮我吗?我是否遗漏了一些明显的函数调用?
- 策略 1(100 个点 <1ms)钻取现有图的 ColumnDataSource 数据并尝试更改所选点。
- 策略 2(每 100 点约 70 毫秒)用新创建的 ColumnDataSource 覆盖图的现有 ColumnDataSource。
- 策略 3(每 100 点约 400 毫秒)是策略 2,然后重新创建 图.
代码存放在 pastebin 上:http://pastebin.com/JvQ1UpzY最相关的部分复制如下。
def refresh_graph(self, selected_points=None, old_idxs=None, new_idxs=None):
# Strategy 1: Cherry pick current plot's source.
# Compute time for 100 points: < 1ms.
if self.strategy == 1:
t1 = datetime.now()
for idx in old_idxs:
self.graph_plot.data_source.data['color'][idx] = 'steelblue'
for idx in new_idxs:
self.graph_plot.data_source.data['color'][idx] = 'red'
print('Strategy #1 completed in {}'.format(datetime.now() - t1))
else:
t3 = datetime.now()
self.coords['color'] = 'steelblue'
self.coords.loc[selected_points, 'color'] = 'red'
new_source = bkmodels.ColumnDataSource(self.coords)
self.graph_plot = self.graph_fig.scatter('x', 'y', source=new_source, color='color', alpha=0.6)
print('Strategy #3 completed in {}'.format(datetime.now() - t3))
return
理想情况下,我希望能够使用策略#1,但它似乎不允许点在客户端浏览器中刷新。
感谢您的帮助!
仅供参考:我正在使用 RHEL 6.X
如果你是流数据,那么这里有一个相关的答案:Timeseries streaming in bokeh
如果您需要一次更新所有内容,那么您可以这样做,我的建议是您的策略 1,它已被证明,例如这里:
https://github.com/bokeh/bokeh/blob/master/examples/app/sliders.py
需要特别注意的是,您确实必须一次性更新所有 source.data
。其中一个假设是列数据源的所有列始终具有相同的长度。更新单个列存在打破此假设的风险,这可能会导致问题。所以您想一次更新所有内容,例如:
# Generate the new curve
x = np.linspace(0, 4*np.pi, N)
y = a*np.sin(k*x + w) + b
source.data = dict(x=x, y=y)