我有一个我想要探索的大型数据集.但是我不想创建多个图.我只想要一个单独的绘图,我可以交互式地更改用于x和y轴的列,并且绘图将自动更新.
我正在尝试用Python / Bokeh使用Bokeh将我的脚本提供给浏览器.但是我不清楚如何让情节更新.我看到很多基础数据源发生变化的例子,但我不想这样做,我只想更改正在绘制的列.
我已经在下面简要介绍了我想要做的事情.它使用两个“Select”小部件来选择数据源的x和y列.这些回调试图改变’Line’字形所指的列.然而,这似乎不起作用.任何的建议都受欢迎.
import numpy as np
from bokeh.models import ColumnDataSource
from bokeh.plotting import Figure
from bokeh.models.widgets import Select,TextInput
from bokeh.models.glyphs import Line
from bokeh.models.layouts import HBox, VBox
from bokeh.io import curdoc
#==============================================================================
#%% Define some Data
#==============================================================================
N = 200
# Define the data to be used
x = np.linspace(0,4.*np.pi,N)
y = 3*np.cos(2*np.pi*x + np.pi*0.2)
z = 0.5*np.sin(2*np.pi*0.8*x + np.pi*0.4)
source = ColumnDataSource({'x':x,'cos':y,'sin':z})
#==============================================================================
#%% Layout
#==============================================================================
TOOLS = "box_select,lasso_select,help"
# create a new plot
plot = Figure(tools=TOOLS, title=None)
# Make a line and connect to data source
glyph = Line(x="x", y="cos", line_color="#F46D43", line_width=6, line_alpha=0.6)
plot.add_glyph(source, glyph)
# Add list boxes for selecting which columns to plot on the x and y axis
yaxis_select = Select(title="Y axis:", value="cos",
options=['x','cos','sin'])
xaxis_select = Select(title="X axis:", value="x",
options=['x','cos','sin'])
# Text input as a title
text = TextInput(title="title", value='my sine wave plotter')
# Layout widgets next to the plot
controls = VBox(text,yaxis_select,xaxis_select)
layout = HBox(controls,plot,width=800)
#==============================================================================
#%% Callbacks
#==============================================================================
# Put callbacks on the list boxes so that when they are changed the columns being
# plotted get changed.
def update_x_axis(attr, old, new):
# Change the column used for the x axis
glyph.x = xaxis_select.value
def update_y_axis(attr, old, new):
# Change the column used for the y axis
glyph.y = yaxis_select.value
yaxis_select.on_change('value', update_y_axis)
xaxis_select.on_change('value', update_x_axis)
#==============================================================================
#%% Add to document root
#==============================================================================
curdoc().add_root(layout)
curdoc().title = "Plotting app"
解决方法:
以下脚本似乎工作得很好.它不使用Bokeh服务器,而是使用CustomJS客户端样式.
import numpy as np
from bokeh.models import ColumnDataSource
from bokeh.plotting import Figure
from bokeh.models.widgets import Select,TextInput
from bokeh.models.layouts import HBox, VBox
import bokeh.io
from bokeh.models import CustomJS
N = 200
# Define the data to be used
x = np.linspace(0,4.*np.pi,N)
y = 3*np.cos(2*np.pi*x + np.pi*0.2)
z = 0.5*np.sin(2*np.pi*0.8*x + np.pi*0.4)
source = ColumnDataSource(data={'x':x,'y':y, 'X': x, 'cos':y,'sin':z})
code="""
var data = source.get('data');
var r = data[cb_obj.get('value')];
var {var} = data[cb_obj.get('value')];
//window.alert( "{var} " + cb_obj.get('value') + {var} );
for (i = 0; i < r.length; i++) {{
{var}[i] = r[i] ;
data['{var}'][i] = r[i];
}}
source.trigger('change');
"""
callbackx = CustomJS(args=dict(source=source), code=code.format(var="x"))
callbacky = CustomJS(args=dict(source=source), code=code.format(var="y"))
# create a new plot
plot = Figure(title=None)
# Make a line and connect to data source
plot.line(x="x", y="y", line_color="#F46D43", line_width=6, line_alpha=0.6, source=source)
# Add list boxes for selecting which columns to plot on the x and y axis
yaxis_select = Select(title="Y axis:", value="cos",
options=['X','cos','sin'], callback=callbacky)
xaxis_select = Select(title="X axis:", value="x",
options=['X','cos','sin'], callback=callbackx)
# Text input as a title
text = TextInput(title="title", value='my sine wave plotter')
# Layout widgets next to the plot
controls = VBox(text,yaxis_select,xaxis_select)
layout = HBox(controls,plot,width=800)
bokeh.io.show(layout)
但是,我把它整理在一起,直到它完成它应该做的事情.而且我不确定为什么CustomJS代码中的部分需要如此复杂.
特别是看起来JS-part中的for循环内部的两条线实际上都是需要的,尽管它们似乎做同样的事情.
因此,在有人能够提出可以解释的事情之前,我不会回答这个问题.