散景:链接线图和散点图

时间:2018-08-09 20:52:59

标签: python bokeh

我有一个线图和一个散点图,它们在概念上通过样本ID链接在一起,即2D散点图上的每个点都对应于该线图上的一条线。

虽然我在使用散点图之前已经完成了链接图的绘制,但是在上述情况下,我没有看到这样的示例-在这种情况下,我选择点,从而选择性地查看线。

是否可以将散点图上的点链接到折线图上的一条线?如果是这样,是否有在线示例实现?

截至2018年8月14日,在网络上搜索bokeh link line and scatter plot并没有在线示例。

2 个答案:

答案 0 :(得分:1)

我知道这有些晚了-也许这段代码会有所帮助吗?

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)

答案 1 :(得分:0)

事实证明,我能够通过使用HoloViews而不是Bokeh来实现这一目标。进行这项工作的相关示例来自Selection1d tap流。

http://holoviews.org/reference/streams/bokeh/Selection1D_tap.html#selection1d-tap

我将为以下示例添加注释版本。

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

import numpy as np
import holoviews as hv
from holoviews.streams import Selection1D
from scipy import stats
hv.extension('bokeh')

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

%%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流。它从points对象中获取点。

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

我从构建该模型中学到的最重要的一点是,必须将点的索引与回归曲线的索引对齐。

我希望这可以帮助其他人使用HoloViews构建出色的视觉效果!