我有一个线图和一个散点图,它们在概念上通过样本ID链接在一起,即2D散点图上的每个点都对应于该线图上的一条线。
虽然我在使用散点图之前已经完成了链接图的绘制,但是在上述情况下,我没有看到这样的示例-在这种情况下,我选择点,从而选择性地查看线。
是否可以将散点图上的点链接到折线图上的一条线?如果是这样,是否有在线示例实现?
截至2018年8月14日,在网络上搜索bokeh link line and scatter plot并没有在线示例。
答案 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构建出色的视觉效果!