Bokeh中的无限水平线

41

有没有办法在 Bokeh 中绘制一条无限长度的水平线?该直线的端点无论用户缩放多少次,都不应变得可见。

这是我目前尝试过的方法,但只会输出一个空画布:

import bokeh.plotting as bk
import numpy as np

p = bk.figure()
p.line([-np.inf,np.inf], [0,0], legend="y(x) = 0")
bk.show(p)

一种方法是将端点设置得非常高/低,同时将图形的x_range和y_range与它们相比非常小。

import bokeh.plotting as bk
import numpy as np

p = bk.figure(x_range=[-10,10])
p.line([-np.iinfo(np.int64).max, np.iinfo(np.int64).max], [0,0], legend="y(x) = 0")
bk.show(p)

不过,我希望有人能提出更加优雅的解决方案。

编辑:已删除过时的解决方案。


1
如果您正在使用线条来强调不同的绘图区域,那么您可能会对新的BoxAnnotations感兴趣! - Eike P.
请考虑更改已接受的答案,SpanBoxAnnotation比旧的已接受答案更好。 - bigreddot
你说得对。两种解决方案都很好。我选择了跨度(span),因为我认为它们更适合我打算使用的目的,而不是无限射线,如果这有任何意义的话。 - Tobias Hotzenplotz
4个回答

62
你正在寻找"spans":
Spans(线型注释)具有单一维度(宽度或高度),并延伸到绘图区域的边缘。
请查看http://docs.bokeh.org/en/latest/docs/user_guide/basic/annotations.html#spans
所以,代码将如下所示:
import numpy as np
import bokeh.plotting as bk
from bokeh.models import Span

p = bk.figure()

# Vertical line
vline = Span(location=0, dimension='height', line_color='red', line_width=3)
# Horizontal line
hline = Span(location=0, dimension='width', line_color='green', line_width=3)

p.renderers.extend([vline, hline])
bk.show(p)

使用这个解决方案,用户可以随意平移和缩放。行尾将永远不会显示出来。

2
我在想:线条、圆圈和其他图形可以基于“源”进行绘制。我们可以将ColumnDataSource输入到其中。这使我们能够更改ColumnDataSource,从而使用Bokeh服务器创建交互式图。我的问题是:像Span这样的注释是否也可以以同样的方式工作?换句话说,我是否可以通过将“位置”的值与滑块链接来移动垂直线条? - Thornhale
1
这个问题在这个帖子中已经得到了解答。 - mosc9575

11

Bokeh中有关线段和射线的文档指出以下解决方案(使用ray):

要创建一个“无限”的射线,它总是延伸到图表的边缘,请将长度设为0。

实际上,下面的代码确实可以生成一条水平的无限线:

import numpy as np
import bokeh.plotting as bk
p = bk.figure()
p.ray(x=[0], y=[0], length=0, angle=0, line_width=1)
p.ray(x=[0], y=[0], length=0, angle=np.pi, line_width=1)
bk.show(p)

6

如果您从中心绘制两条光线,当您放大或缩小时它们不会变小,因为长度是以像素为单位的。所以看起来就像这样:

p.ray(x=[0],y=[0],length=300, angle=0, legend="y(x) = 0")
p.ray(x=[0],y=[0],length=300, angle=np.pi, legend="y(x) = 0")

但是,如果用户在任何方向上移动视图,则射线的末端会显示出来。如果您可以完全防止用户平移(即使他们缩放),那么这是一个更好的水平线代码。

如果用户可以随意缩放和平移,则据我所知,没有好的方法可以得到您描述的水平线。


谢谢!稍加修改,射线就能发挥作用了。我正在编辑我的问题。然而,它并不是非常优雅。 - Tobias Hotzenplotz
现在Spans可用,应该取代此答案。 - bigreddot

1

如果您想知道如何将span与时间序列结合使用,请将日期转换为Unix时间戳:

start_date = time.mktime(datetime.date(2018, 3, 19).timetuple())*1000
vline = Span(location=start_date,dimension='height', line_color='red',line_width=3)

或者查看此链接以获得完整示例。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接