小能豆

如何使用 CDS 列设置多线字形的“line_dash”?

py

我正在用该方法绘制多线multi_line

from bokeh.plotting import figure, show
from bokeh.models import ColumnDataSource

source = ColumnDataSource(data=dict(
        x=[3, 3],
        y=[4, 4],
        xs1=[[1, 2, 3], [2, 3, 4]],
        ys1=[[6, 7, 2], [4, 5, 7]],
        xs2=[[8, 9], [10, 11, 12]],
        ys2=[[6, 7], [7, 8, 9]],        
        color=['red', 'green'],
        width=[5, 1],
        dash=['solid', 'dashed']
    )
)

p = figure(
    plot_width=400, 
    plot_height=400,
    tools='lasso_select,pan,wheel_zoom'
)

p.multi_line(
    xs='xs1',
    ys='ys1',
    source=source,
    color='color',
    line_join='round',
    line_width='width',    # this is working with the column name, despite the documentatio say nothing
    # line_dash='dash'     # this is not working
)

show(p)

color可以在多行源 CDS 上设置、alpha或 的列line_width,以便以不同的方式绘制每条线。但这不能应用于line_dash属性。我想制作主线solid和其余的dashed

如果我使用此主线的字形line,那么我将失去性能,因为我需要在每个图上同时更新多个字形。

另一方面,我认为文档中缺少一些内容,line_width因为可以将 CDS 列分配给此方法参数并且它可以工作:

alpha (float) – an alias to set all alpha keyword args at once
color (Color) – an alias to set all color keyword args at once
>> line_width (float) - should this be added because it works with CDS columns?

有没有办法为line_dash属性分配一列?

我没有深入测试其余属性。


阅读 26

收藏
2025-01-02

共2个答案

小能豆

尽管您询问的是与有关的问题MultiLine,但是这个问题的答案与分段图的虚线是否可以由源数据定义?相同,即line_dash目前不支持“矢量化”该属性(截至0.12.16),如果您现在想要不同的虚线,则必须单独调用line。

2025-01-02
小能豆

在 Bokeh 中,multi_line确实支持某些属性绑定到ColumnDataSource(CDS)列,例如colorline_width等。然而,目前(截至Bokeh 3.x版本),line_dash属性不支持直接绑定到CDS列。换句话说,line_dash无法像colorline_width一样,从CDS列动态设置每条线的样式。

解决方法

尽管multi_line无法直接通过CDS设置line_dash,您可以通过以下替代方法实现目标:

1. 分割多线为多个multi_line调用

使用多个multi_line调用,每个调用分别绘制具有不同line_dash样式的线。虽然增加了图形元素,但可以保留使用CDS的能力。

from bokeh.plotting import figure, show
from bokeh.models import ColumnDataSource

source = ColumnDataSource(data=dict(
    xs1=[[1, 2, 3], [2, 3, 4]],
    ys1=[[6, 7, 2], [4, 5, 7]],
    xs2=[[8, 9], [10, 11, 12]],
    ys2=[[6, 7], [7, 8, 9]],
    color1=['red', 'green'],
    color2=['blue', 'orange'],
    width=[5, 1]
))

p = figure(plot_width=400, plot_height=400)

# First set of lines (solid)
p.multi_line(
    xs='xs1',
    ys='ys1',
    source=source,
    color='color1',
    line_width='width',
    line_dash='solid'
)

# Second set of lines (dashed)
p.multi_line(
    xs='xs2',
    ys='ys2',
    source=source,
    color='color2',
    line_width='width',
    line_dash='dashed'
)

show(p)

2. 使用循环动态添加单线

通过循环line字形来分别设置每条线的样式。尽管性能可能稍差,但这种方法允许您控制每条线的样式。

for i in range(len(source.data['xs1'])):
    p.line(
        x=source.data['xs1'][i],
        y=source.data['ys1'][i],
        color=source.data['color1'][i],
        line_width=source.data['width'][i],
        line_dash='solid'
    )

for i in range(len(source.data['xs2'])):
    p.line(
        x=source.data['xs2'][i],
        y=source.data['ys2'][i],
        color=source.data['color2'][i],
        line_width=source.data['width'][i],
        line_dash='dashed'
    )

3. 通过扩展 Bokeh 添加自定义属性

如果需要动态绑定line_dash到CDS列,可以扩展 Bokeh 的功能。创建一个自定义 JavaScript 模型,可以让line_dash支持CDS绑定。这需要更多的开发工作,但如果性能和动态性是关键要求,这是一个高级选项。


关于文档问题

您提到line_width的行为不在文档中清楚描述,这是一个值得反馈给 Bokeh 开发团队的地方。Bokeh 的开源性质允许用户在其 GitHub 仓库上提交问题或功能请求。您可以将您的发现和需求记录下来,可能会在未来版本中获得支持。

希望这些方法可以解决您的问题!

2025-01-02