python散景动态更新分类x_range

python bokeh dynamically update categorical x_range

我想在散景中创建烛台图,并根据用户通过 MultiSelect 小部件的输入动态更新 x 轴。基本上,用户会在 MultiSelect 中选择一些项目,然后我希望这些成为 x 轴的值。我已经设置了 MultiSelect 小部件,并通过将 DataTable 附加到 MultiSelect 并使其相应更新(确实如此)来确认它正在工作。我只需要帮助从 MultiSelect 小部件检索值并将它们设置为我的 plot.x_range。基于一些 github/issues 的帖子(比如这个:https://github.com/bokeh/bokeh/issues/4022),我尝试使用 FactorRange,但它不起作用。目前的行为是 x 轴标签保持设置为在 MultiSelect 的初始配置期间设置的值('aaa' 和 'bbb'),并且当我在 MultiSelect 中选择不同的值时不要改变小部件。

这是一个代码示例:

### SET UP SOURCE DF INFO ###
tab2_source = ColumnDataSource(df)
tab2_original_source = ColumnDataSource(df)
columns_t2 = [TableColumn(field='Gene', title='Gene'), TableColumn(field='row_min', title='min'), TableColumn(field='row_max', title='max'), 
             TableColumn(field='quantile_25', title='25th quantile'), TableColumn(field='quantile_50', title='50th quantile'), TableColumn(field='quantile_75', title='75th quantile')]
data_table_t2 = DataTable(source=tab2_source, columns=columns_t2, reorderable=False)

### STUFF FOR THE WIDGETS ###
# customJS stuff
tab2_callback_code = """
var t2_data = tab2_source.data;
var t2_original_data = tab2_original_source.data;
var gene_t2 = gene_select_obj_t2.value;
console.log("gene: " + gene_t2);
for (var key in t2_original_data) {
    t2_data[key] = [];
    for (var i = 0; i < t2_original_data['Gene'].length; ++i) {
        if (t2_original_data['Gene'][i] === gene_t2[0] || t2_original_data['Gene'][i] === gene_t2[1]) {
            t2_data[key].push(t2_original_data[key][i]);
        }
    }
}

tab2_source.change.emit();
target_obj_t2.change.emit();
"""

# make drop-down selectors
select_gene_t2 = MultiSelect(title = "Select up to 2 Genes to View:", value=['aaa', 'bbb'], options=list(df.Gene.unique()))

# define the callback objects now that the select widgets exist
tab2_callback = CustomJS(
    args=dict(tab2_source=tab2_source,
             tab2_original_source=tab2_original_source,
             gene_select_obj_t2=select_gene_t2,
             target_obj_t2=data_table_t2),
    code=tab2_callback_code)

# connect the callbacks to the filter widgets
select_gene_t2.js_on_change('value', tab2_callback)


## PLOTTING ##
p2 = figure(plot_width=500, plot_height=400, title='Avg Gene Exp', y_range=(-2,12), x_range=FactorRange())
p2.x_range.factors = list(select_gene_t2.value)
p2.vbar(x='Gene', top='quantile_75', bottom='quantile_25', source=tab2_source, width=0.5, fill_color="#D5E1DD", line_color="black")
tab2 = Panel(child=column(select_gene_t2, p2, data_table_t2), title="Exp by Gene")
tabs = Tabs(tabs=[tab2])
save(tabs)

对于任何感兴趣的人,这是我找到的最佳解决方案:

将此行添加到 tab2_callback_code(plot_xr 引用我的图 p2 - 您还需要在 CustomJS args dict 中添加这些引用):

plot_xr.x_range.factors = gene_t2;

在调用 tab2_callback_code 之前实例化图形也很重要。这对我有用,现在我的 x_range 值随着我在 MultiSelect 中 select 不同的选项而改变。