Python Bokeh:链接线图和散点图

Python Bokeh:链接线图和散点图,python,bokeh,Python,Bokeh,我有一个线状图和散点图,它们在概念上由样本ID链接,即2D散点图上的每个点对应于线状图上的一条线 虽然我在使用散点图之前已经完成了链接打印,但我没有看到上面这种情况的例子——我选择点,从而有选择地查看线 是否可以将散点图上的点连接到线图上的线?如果有,是否有在线的示例实现 截至2018年8月14日,在网上搜索没有任何示例。我知道这有点晚了,但这段代码可能会有所帮助 import numpy as np from bokeh.io import output_file, show from bok

我有一个线状图和散点图,它们在概念上由样本ID链接,即2D散点图上的每个点对应于线状图上的一条线

虽然我在使用散点图之前已经完成了链接打印,但我没有看到上面这种情况的例子——我选择点,从而有选择地查看线

是否可以将散点图上的点连接到线图上的线?如果有,是否有在线的示例实现


截至2018年8月14日,在网上搜索没有任何示例。

我知道这有点晚了,但这段代码可能会有所帮助

import numpy as np
from bokeh.io import output_file, show
from bokeh.layouts import gridplot
from bokeh.models import ColumnDataSource
from bokeh.plotting import figure
from bokeh.models import Circle,MultiLine

def play():
    x = np.linspace(0,10,100)
    y = np.random.rand(100)
    xs = np.random.rand(100,3)
    ys = np.random.normal(size=(100,3))
    xp = [list(xi) for xi in xs] # Because Multi-List does not like numpy arrays
    yp = [list(yi) for yi in ys]
    output_file('play.html')
    source = ColumnDataSource(data=dict(x=x,y=y,xp=xp,yp=yp))
    TOOLS = 'box_select'
    left = figure(tools=TOOLS,plot_width=700,plot_height=700)
    c1 = left.circle('x','y',source=source)
    c1.nonselection_glyph = Circle(fill_color='gray',fill_alpha=0.4,
                                   line_color=None)
    c1.selection_glyph = Circle(fill_color='orange',line_color=None)
    right = figure(tools=TOOLS,plot_width=700,plot_height=700)
    c2 = right.multi_line(xs='xp',ys='yp',source=source)
    c2.nonselection_glyph = MultiLine(line_color='gray',line_alpha=0.2)
    c2.selection_glyph = MultiLine(line_color='orange')
    p = gridplot([[left, right]])
    show(p)

事实证明,我能够通过使用全息视图而不是Bokeh实现这一点。执行此操作的相关示例来自
Selection1d tap

我将对下面的示例进行注释

首先,我们从进口开始。(注意:所有这些都假设工作是在Jupyter笔记本中完成的。)

首先,我们为图表设置一些样式选项。根据我的经验,我通常在设计图表样式之前先构建图表

%%opts Scatter [color_index=2 tools=['tap', 'hover'] width=600] {+framewise} (marker='triangle' cmap='Set1' size=10)
%%opts Overlay [toolbar='above' legend_position='right'] Curve (line_color='black') {+framewise}
下面的函数生成数据

def gen_samples(N, corr=0.8):
    xx = np.array([-0.51, 51.2])
    yy = np.array([0.33, 51.6])
    means = [xx.mean(), yy.mean()]  
    stds = [xx.std() / 3, yy.std() / 3]
    covs = [[stds[0]**2          , stds[0]*stds[1]*corr], 
            [stds[0]*stds[1]*corr,           stds[1]**2]] 

    return np.random.multivariate_normal(means, covs, N)

data = [('Week %d' % (i%10), np.random.rand(), chr(65+np.random.randint(5)), i) for i in range(100)]
sample_data = hv.NdOverlay({i: hv.Points(gen_samples(np.random.randint(1000, 5000), r2))
                            for _, r2, _, i in data})
真正的魔法从这里开始。首先,我们使用
hv.Scatter
对象设置散点图

points = hv.Scatter(data, ['Date', 'r2'], ['block', 'id']).redim.range(r2=(0., 1))
然后,我们创建一个
Selection1D
流。它从
对象中提取点

stream = Selection1D(source=points)
然后我们创建一个函数来显示右侧的回归图。有一个“默认”的空绘图,然后有一个
hv.DynamicMap
调用的回调

empty = (hv.Points(np.random.rand(0, 2)) * hv.Curve(np.random.rand(0, 2))).relabel('No selection')

def regression(index):
    if not index:
        return empty
    scatter = sample_data[index[0]]
    xs, ys = scatter['x'], scatter['y']
    slope, intercep, rval, pval, std = stats.linregress(xs, ys)
    xs = np.linspace(*scatter.range(0)+(2,))
    reg = slope*xs+intercep
    return (scatter * hv.Curve((xs, reg))).relabel('r2: %.3f' % slope)
现在,我们创建DynamicMap,动态加载回归曲线数据

reg = hv.DynamicMap(regression, kdims=[], streams=[stream])

# Ignoring annotation for average - it is not relevant here.    
average = hv.Curve(points, 'Date', 'r2').aggregate(function=np.mean)
最后,我们显示了图

points * average + reg
我从构建中学到的最重要的一点是,点的索引必须与回归曲线的索引对齐


我希望这能帮助其他人使用HoloView构建很棒的viz

这当然是可能的,事实上有很多种方式,这就是为什么提出的问题太广泛的原因。谢谢@bigreddot的反馈!文档中有这样的例子吗?我没能在下面找到任何东西。我将更新问题,使其更加具体。独立的博克输出?Bokeh服务器应用程序?一般来说,你需要更具体一些,这样才能为你尝试过的东西提供一些实际的代码,寻求帮助完成、修复或改进它。我在想Jupyter笔记本中的Bokeh输出。抱歉,@bigreddot,如果我问这个问题的方式让你感到沮丧的话。也就是说,我真的不知道从哪里开始,因此我没有代码。对于散点图,我可以在独立的Bokeh输出和服务器应用程序中进行链接刷牙,但我的心智模型中缺少了阻止我以更好的方式提问的东西。如果这个地方不适合问这个问题,那么我应该去哪里?问题追踪器在我听来不太合适;那么谷歌群组呢?谢谢你的回复,@Samir!这是一次很好的尝试。然而,我发现HoloView的使用使构建更容易,也更不繁琐。我希望你也能试一试!
points * average + reg