python – 以交互方式更改正在绘制的列的Bokeh

我有一个我想要探索的大型数据集.但是我不想创建多个图.我只想要一个单独的绘图,我可以交互式地更改用于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循环内部的两条线实际上都是需要的,尽管它们似乎做同样的事情.

因此,在有人能够提出可以解释的事情之前,我不会回答这个问题.

上一篇:Python在交互式会话中登录


下一篇:jenkins 执行远程脚本问题