首页 > 解决方案 > 在 python bokeh 中,如何在没有 js 的情况下以交互方式修改 fill_color 的字段?

问题描述

我正在尝试使用散景来绘制虹膜数据并以交互方式修改圆圈的填充颜色,但我遇到了问题。我将情节和圆圈称为以下内容:

plot = figure(plot_height=600, plot_width=1000, title="Iris Data",
              x_axis_label = 'Sepal length (cm)',
              y_axis_label = 'Sepal width (cm)',
              tools = "crosshair, pan, reset, save, wheel_zoom")
plot_circle = plot.circle(x='sepal_length', y='sepal_width', source=source,
                         line_color=None, fill_color={'field':'petal_width','transform':color_mapper},
                         size='size', fill_alpha = 0.2)

这可行,但是当我尝试在回调中添加交互性时,我不清楚如何将 fill_color 参数中的“字段”参数修改为圆形。我试过这个:

def update_bubble_color(attrname, old, new):
    if new=='petal_width':
        color_mapper.low  = min(flowers['petal_width'])
        color_mapper.high = max(flowers['petal_width'])
        fill_color.field='petal_width'
        return
    if new=='petal_length':
        color_mapper.low  = min(flowers['petal_length'])
        color_mapper.high = max(flowers['petal_length'])
        fill_color.field='petal_length'
        return
select_bubble_color.on_change('value', update_bubble_color)

颜色映射器限制已正确处理,但颜色未根据新选择进行缩放。当我尝试使用 fill_color.field='petal_length' 将其更改为 petal_length 时,我收到“'name 'fill_color' is not defined”错误。

非常感谢任何帮助!

下面的完整代码供参考

import numpy as np

from bokeh.io import curdoc
from bokeh.layouts import row, column

from bokeh.models import ColumnDataSource, LinearColorMapper
from bokeh.models.widgets import Select
from bokeh.plotting import figure

# Load Data
from bokeh.sampledata.iris import flowers

# Global constants (even if python dies not like it)
min_bubble_size = 10
max_bubble_size = 90

def get_scaled_size(vector):
    min_vector = min(vector)
    max_vector = max(vector)
    scaling = (max_bubble_size-min_bubble_size)/(max_vector-min_vector)
    scaled_size = [ scaling*(item-min_vector) + min_bubble_size for item in vector]
    return scaled_size

# Color Mapper
color_mapper = LinearColorMapper(palette='Inferno256',
                                 low = min(flowers['petal_width']),
                                 high = max(flowers['petal_width']) )

# Define source
flowers['size'] = get_scaled_size(flowers['petal_length'])
source = ColumnDataSource(flowers)

# Set up plot
plot = figure(plot_height=600, plot_width=1000, title="Iris Data",
              x_axis_label = 'Sepal length (cm)',
              y_axis_label = 'Sepal width (cm)',
              tools = "crosshair, pan, reset, save, wheel_zoom")
plot_circle = plot.circle(x='sepal_length', y='sepal_width', source=source,
                         line_color=None, fill_color={'field':'petal_width','transform':color_mapper},
                         size='size', fill_alpha = 0.2)

# Set up widgets
select_bubble_size = Select(title   ='Bubble size by', value='petal_width',
                            options = ['petal_width','petal_length'],
                            width   = 200)

select_bubble_color = Select(title   ='Bubble color by', value='petal_width',
                            options = ['petal_width', 'petal_length'],
                            width   = 200)

# Colorbar
from bokeh.models import ColorBar
bar = ColorBar(color_mapper=color_mapper,location=(0,0))
plot.add_layout(bar, 'left')

# Set up callbacks=
    # Bubble size call back
def update_bubble_size(attrname, old, new):
    if new=='petal_width':
        source.data['size'] =  get_scaled_size(flowers['petal_width'])
        return
    if new=='petal_length':
        source.data['size']  = get_scaled_size(flowers['petal_length'])
        return
select_bubble_size.on_change('value', update_bubble_size)

    # bubble color call back
def update_bubble_color(attrname, old, new):
    if new=='petal_width':
        color_mapper.low  = min(flowers['petal_width'])
        color_mapper.high = max(flowers['petal_width'])
        fill_color.field='petal_width'
        return
    if new=='petal_length':
        color_mapper.low  = min(flowers['petal_length'])
        color_mapper.high = max(flowers['petal_length'])
        fill_color.field='petal_length'
        return
select_bubble_color.on_change('value', update_bubble_color)

# Set up layouts and add to document
curdoc().add_root(column(plot, row(select_bubble_size,select_bubble_color), width=800))
curdoc().title = "Iris Data"

标签: pythonbokeh

解决方案


fill_color是字形的一个属性,您需要通过字形访问它:

plot_circle.glyph.fill_color

在您的脚本中,任何地方都没有自由变量fill_color,这是NameError.


推荐阅读