【问题标题】:Bokeh: Interact with legend label text散景:与图例标签文本交互
【发布时间】:2018-01-23 22:06:30
【问题描述】:

有什么方法可以交互地更改 Bokeh 中的图例标签文本?

我已阅读https://github.com/bokeh/bokeh/issues/2274How to interactively display and hide lines in a Bokeh plot?,但都不适用。

我不需要修改颜色或任何比更改标签文本更复杂的东西,但我找不到方法。

【问题讨论】:

    标签: python bokeh


    【解决方案1】:

    我希望这个答案可以帮助其他有类似问题的人。

    有一个解决这个问题的方法:从版本 0.12.3 开始,您的图例可以通过用于生成给定元素的 ColumnDataSource 对象进行动态修改。例如:

    source_points = ColumnDataSource(dict(
                    x=[1, 2, 3, 4, 5, 6],
                    y=[2, 1, 2, 1, 2, 1],
                    color=['blue','red','blue','red','blue','red'],
                    category=['hi', 'lo', 'hi', 'lo', 'hi', 'lo']
                    ))
    self._figure.circle('x',
                        'y',
                        color='color',
                        legend='category',
                        source=source_points)
    

    然后您应该能够通过再次设置类别值来更新图例,例如:

    # must have the same length
    source_points.data['category'] = ['stack', 'flow', 'stack', 'flow', 'stack', 'flow']
    

    注意categorycolor 之间的关系。如果你有这样的事情:

    source = ColumnDataSource(dict(
            x=[1, 2, 3, 4, 5, 6],
            y=[2, 1, 2, 1, 2, 1],
            color=['blue','red','blue','red','blue','red'],
            category=['hi', 'hi', 'hi', 'lo', 'hi', 'lo']
        ))
    

    然后第二个hi 也会显示为蓝色。它只匹配第一次出现。

    【讨论】:

    • 如果有人想知道,现在您必须使用 legend_field="category"(或您在字典中使用的任何字段)代替 legend="category"(已弃用)。
    【解决方案2】:

    从 Bokeh 0.12.1 开始,目前似乎不支持此功能。 Legend 对象有一个 legends 属性,可将文本映射到字形列表:

    {
        "foo": [circle1], 
        "bar": [line2, circle2]
    }
    

    理想情况下,您可以更新此legends 属性以使其重新渲染。但是看看the source code,它似乎在初始化时使用了该值,但如果值发生变化,则没有强制重新渲染的管道。一种可能的解决方法是更改​​legends 的值,然后立即设置一些其他确实 触发重新渲染的属性。

    无论如何,在更新上进行这项工作应该不会做太多工作,并且对于新贡献者来说将是一个不错的 PR。我鼓励您在 GitHub issue tracker 上提交功能请求问题,如果您有能力通过 Pull Request 来实现它(我们总是很乐意帮助新的贡献者入门并回答问题)

    【讨论】:

      【解决方案3】:

      在我的例子中,我使它与下一个代码一起工作:

      from bokeh.plotting import figure, show
      
      # Create and show the plot
      plt = figure()
      handle = show(plt, notebook_handle=True)
      
      # Update the legends without generating the whole plot once shown
      for legend in plt.legend:
          for legend_item, new_value in zip(legend.items, new_legend_values):
              legend_item.label['value'] = new_value
      push_notebook(handle=handle)
      

      在我的例子中,我正在绘制一些分布,然后以交互方式更新(就像分布变化的动画)。在图例中,我有随时间变化的分布参数,我需要在每次迭代时更新它们,因为它们会发生变化。

      请注意,此代码仅适用于 Jupyter 笔记本。

      【讨论】:

      • 您能否举一个更完整的例子,我一直收到“ValueError:PATCH-DOC 消息需要至少一个事件”错误。
      • 我猜这是由不同版本的散景引起的。您应该在回溯中检查哪一行失败,以及在您的版本的失败函数的文档中,期待什么。如果您没有找到解决方案,请在 stackoverlow 中发布一个新问题,并随时添加指向此答案的链接。
      【解决方案4】:

      我最终只是每次都重新绘制整个图表,因为在我的情况下线的数量也有所不同。

      一个小型的 Jupyter 笔记本示例:

      from bokeh.io import show
      from bokeh.plotting import figure
      from bokeh.palettes import brewer
      from math import sin, pi
      output_notebook()   
      
      def update(Sine):
          p = figure() 
          r = []
          for i in range(sines.index(Sine) + 1):
              y = [sin(xi/(10*(i+1))) for xi in x]
              r.append(p.line(x, y, legend=labels[i], color=colors[i], line_width = 3))
      
          show(p, notebook_handle=True)
          push_notebook()  
      
      sines = ["one sine", "two sines", "three sines"]
      labels = ["First sine", "second sine", "Third sine"]
      colors = brewer['BuPu'][3]
      x = [i for i in range(100)]
      
      interact(update, Sine=sines)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-03-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-09-25
        • 1970-01-01
        • 1970-01-01
        • 2017-06-06
        相关资源
        最近更新 更多