Javascript 如何删除/添加Bokeh热图中的行并保持行高?

Javascript 如何删除/添加Bokeh热图中的行并保持行高?,javascript,bokeh,heatmap,Javascript,Bokeh,Heatmap,我制作了一个链接到CheckBoxGroup的Bokeh热图,以便CheckBoxGroup中的活动项与热图中显示的行相对应。i、 e.选中/取消选中复选框组中的复选框可添加或删除热图中的行。这一切都很好,除了我希望热图的行保持相同的高度,无论热图中有多少行。实际情况是保留热图的原始高度,并调整行的大小以适应原始高度 我这里有一个MWE: from bokeh.io import output_file, show from bokeh.models import

我制作了一个链接到CheckBoxGroup的Bokeh热图,以便CheckBoxGroup中的活动项与热图中显示的行相对应。i、 e.选中/取消选中复选框组中的复选框可添加或删除热图中的行。这一切都很好,除了我希望热图的行保持相同的高度,无论热图中有多少行。实际情况是保留热图的原始高度,并调整行的大小以适应原始高度

我这里有一个MWE:

        from bokeh.io import output_file, show
        from bokeh.models import ColorBar, ColumnDataSource, LinearColorMapper
        from bokeh.plotting import figure
        from bokeh.transform import transform
        from bokeh.layouts import row, widgetbox
        from bokeh.models.callbacks import CustomJS
        from bokeh.models.widgets import CheckboxGroup
        import pandas as pd


        output_file("test.html")

        # set up data
        df = pd.DataFrame([["1", "1", 0.09], ["2", "1", 0.21], ["3", "1", 0.31], ["4", "1", 0.41],
                           ["1", "2", 0.5], ["2", "2", 0.61], ["3", "2", 0.71], ["4", "2", 0.81]],
                          columns=["x", "y", "values"])

        # source data for plot
        source = ColumnDataSource(df)

        # original source dataset, does not get changed
        savedsource = ColumnDataSource(df)

        # set up plot
        colors = ["#5A736F", "#75968f", "#a5bab7", "#c9d9d3", "#e2e2e2", "#dfccce", "#ddb7b1", "#cc7878", "#933b41",
                  "#550b1d"]
        mapper = LinearColorMapper(palette=colors, low=0, high=1)

        p = figure(title="Test", plot_width=200, plot_height=240,
                   x_range=["1", "2", "3", "4"], y_range=["1", "2"],
                   toolbar_location=None, tools="", x_axis_location="above")

        p.rect(x="x", y="y", width=1, height=1, source=source,
               line_color=None, fill_color=transform('values', mapper))

        p.axis.axis_line_color = None
        p.axis.major_tick_line_color = None
        p.axis.major_label_text_font_size = "9pt"
        p.axis.major_label_standoff = 0
        p.xaxis.major_label_orientation = 1.0

        # Create the checkbox selection element
        rows = ["1", "2"]
        selection = CheckboxGroup(labels=rows,
                                  active=[i for i in range(0, len(rows))])

        callback = CustomJS(args=dict(source=source, savedsource=savedsource, plot=p),
                            code="""

                    // get selected checkboxes
                    var active = cb_obj.active;

                    // get full original dataset
                    var origdata = savedsource.data;

                    // number of x-values
                    var numxs = plot.x_range.factors.length;

                    // this will be the new dataset
                    var newdata = {"index": [], "values": [], "x": [], "y": []};

                    // new y labels
                    var newlabels = [];

                    // slice out the data we want and put it into newdata
                    var i, j;
                    for (j=0; j<active.length; j++)
                    {
                        i = active[j]; // next active checkbox

                        newdata.index.push(...origdata.index.slice(i*numxs, i*numxs + numxs));
                        newdata.values.push(...origdata.values.slice(i*numxs, i*numxs + numxs));
                        newdata.x.push(...origdata.x.slice(i*numxs, i*numxs + numxs));
                        newdata.y.push(...origdata.y.slice(i*numxs, i*numxs + numxs));

                        newlabels.push(...origdata.y.slice(i*numxs, i*numxs + 1));
                    }

                    // replace the plot source data with newdata
                    source.data = newdata;

                    // update the yrange to reflect the deleted data
                    plot.y_range.factors = newlabels;
                    plot.y_range.end = newlabels.length;
                    source.change.emit();
                """)

        selection.js_on_change('active', callback)

        layout = row(widgetbox(selection), p)

        show(layout)

从bokeh.io导入输出文件,显示
从bokeh.models导入ColorBar、ColumnDataSource、LinearColorMapper
从bokeh.plotting导入图形
从bokeh.transform导入transform
从bokeh.layouts导入行,widgetbox
从bokeh.models.callbacks导入CustomJS
从bokeh.models.widgets导入CheckboxGroup
作为pd进口熊猫
输出文件(“test.html”)
#设置数据
df=pd.数据帧([[“1”,“1”,0.09],“2”,“1”,0.21],“3”,“1”,“0.31],“4”,“1”,0.41],
["1", "2", 0.5], ["2", "2", 0.61], ["3", "2", 0.71], ["4", "2", 0.81]],
列=[“x”、“y”、“值”])
#绘图的源数据
source=ColumnDataSource(df)
#原始源数据集,未被更改
savedsource=列数据源(df)
#设点
颜色=[“5A736F”、“75968f”、“a5bab7”、“c9d9d3”、“e2e2e2”、“dfccce”、“ddb7b1”、“cc7878”、“933b41”,
“#550b1d”]
映射器=线性颜色映射器(调色板=颜色,低=0,高=1)
p=图(title=“测试”,绘图宽度=200,绘图高度=240,
x_范围=[“1”、“2”、“3”、“4”],y_范围=[“1”、“2”],
工具栏_位置=无,工具=”,x_轴_位置=“以上”)
p、 矩形(x=“x”,y=“y”,宽度=1,高度=1,震源=震源,
线条颜色=无,填充颜色=变换(“值”,映射器))
p、 axis.axis\u line\u color=无
p、 axis.major\u刻度线\u线\u颜色=无
p、 axis.major\u标签\u文本\u font\u size=“9pt”
p、 轴长标签距离=0
p、 xaxis.major_标签_方向=1.0
#创建复选框选择元素
行=[“1”,“2”]
选择=复选框组(标签=行,
活动=[i代表范围内的i(0,len(行))])
callback=CustomJS(args=dict(source=source,savedsource=savedsource,plot=p),
代码=”“
//获取所选复选框
var active=cb_obj.active;
//获取完整的原始数据集
var origdata=savedsource.data;
//x值的数目
var numxs=plot.x_range.factors.length;
//这将是新的数据集
var newdata={“索引”:[],“值”:[],“x”:[],“y”:[]};
//新的y标签
var newlabels=[];
//将我们需要的数据切片并放入新数据中
varⅠ,j;

对于
CustomJS
回调的最后几行中的(j=0;j),在
更新yrange以反映删除的数据之后,您可以显式更改范围-这正是使绘图按其方式运行的原因


只需删除
source.data=newdata;
-您不需要
source.change.emit()
或者,因为您更改了整个数据属性。

CustomJS
回调的最后几行中,在
更新yrange以反映删除的数据之后,您明确地更改了范围-这正是使绘图按其方式运行的原因


只要删除
source.data=newdata;
-您也不需要
source.change.emit();
,因为您更改了整个数据属性。

这里需要的是调整回调中的
frame\u height
并调用
plot.properties.height.change.emit()
-此处提供了一些帮助:

最终MWE:

from bokeh.io import output_file, show
from bokeh.models import ColorBar, ColumnDataSource, LinearColorMapper
from bokeh.plotting import figure
from bokeh.transform import transform
from bokeh.layouts import row, widgetbox
from bokeh.models.callbacks import CustomJS
from bokeh.models.widgets import CheckboxGroup
import pandas as pd

output_file("test.html")

# set up data
df = pd.DataFrame([["1", "1", 0.09], ["2", "1", 0.21], ["3", "1", 0.31], ["4", "1", 0.41],
                   ["1", "2", 0.5], ["2", "2", 0.61], ["3", "2", 0.71], ["4", "2", 0.81]],
                  columns=["x", "y", "values"])

# source data for plot
source = ColumnDataSource(df)

# original source dataset, does not get changed
savedsource = ColumnDataSource(df)

# set up plot
colors = ["#5A736F", "#75968f", "#a5bab7", "#c9d9d3", "#e2e2e2", "#dfccce", "#ddb7b1", "#cc7878", "#933b41",
          "#550b1d"]
mapper = LinearColorMapper(palette=colors, low=0, high=1)

p = figure(title="Test", plot_width=200, plot_height=240,
           x_range=["1", "2", "3", "4"], y_range=["1", "2"],
           toolbar_location=None, tools="", x_axis_location="above")

p.frame_height = 240  # 2 rows of height 120

p.rect(x="x", y="y", width=1, height=1, source=source,
       line_color=None, fill_color=transform('values', mapper))

p.axis.axis_line_color = None
p.axis.major_tick_line_color = None
p.axis.major_label_text_font_size = "9pt"
p.axis.major_label_standoff = 0
p.xaxis.major_label_orientation = 1.0

# Create the checkbox selection element
rows = ["1", "2"]
selection = CheckboxGroup(labels=rows,
                          active=[i for i in range(0, len(rows))])

callback = CustomJS(args=dict(source=source, savedsource=savedsource, plot=p),
                    code="""

                    // get selected checkboxes
                    var active = cb_obj.active;

                    // get full original dataset
                    var origdata = savedsource.data;

                    // number of x-values
                    var numxs = plot.x_range.factors.length;

                    // this will be the new dataset
                    var newdata = {"index": [], "values": [], "x": [], "y": []};

                    // new y labels
                    var newlabels = [];

                    // slice out the data we want and put it into newdata
                    var i, j;
                    for (j=0; j<active.length; j++)
                    {
                        i = active[j]; // next active checkbox

                        newdata.index.push(...origdata.index.slice(i*numxs, i*numxs + numxs));
                        newdata.values.push(...origdata.values.slice(i*numxs, i*numxs + numxs));
                        newdata.x.push(...origdata.x.slice(i*numxs, i*numxs + numxs));
                        newdata.y.push(...origdata.y.slice(i*numxs, i*numxs + numxs));

                        newlabels.push(...origdata.y.slice(i*numxs, i*numxs + 1));
                    }

                    // replace the plot source data with newdata
                    source.data = newdata;

                    // update the yrange to reflect the deleted data
                    plot.y_range.factors = newlabels;
                    plot.y_range.end = newlabels.length;

                    // update plot height
                    new_height = newlabels.length * 120; //rowheight is 120
                    plot.frame_height = new_height;
                    plot.properties.height.change.emit();
                """)

selection.js_on_change('active', callback)

layout = row(widgetbox(selection), p)

show(layout)
从bokeh.io导入输出文件,显示
从bokeh.models导入ColorBar、ColumnDataSource、LinearColorMapper
从bokeh.plotting导入图形
从bokeh.transform导入transform
从bokeh.layouts导入行,widgetbox
从bokeh.models.callbacks导入CustomJS
从bokeh.models.widgets导入CheckboxGroup
作为pd进口熊猫
输出文件(“test.html”)
#设置数据
df=pd.数据帧([[“1”,“1”,0.09],“2”,“1”,0.21],“3”,“1”,“0.31],“4”,“1”,0.41],
["1", "2", 0.5], ["2", "2", 0.61], ["3", "2", 0.71], ["4", "2", 0.81]],
列=[“x”、“y”、“值”])
#绘图的源数据
source=ColumnDataSource(df)
#原始源数据集,未被更改
savedsource=列数据源(df)
#设点
颜色=[“5A736F”、“75968f”、“a5bab7”、“c9d9d3”、“e2e2e2”、“dfccce”、“ddb7b1”、“cc7878”、“933b41”,
“#550b1d”]
映射器=线性颜色映射器(调色板=颜色,低=0,高=1)
p=图(title=“测试”,绘图宽度=200,绘图高度=240,
x_范围=[“1”、“2”、“3”、“4”],y_范围=[“1”、“2”],
工具栏_位置=无,工具=”,x_轴_位置=“以上”)
p、 框架高度=240#两排高度120
p、 矩形(x=“x”,y=“y”,宽度=1,高度=1,震源=震源,
线条颜色=无,填充颜色=变换(“值”,映射器))
p、 axis.axis\u line\u color=无
p、 axis.major\u刻度线\u线\u颜色=无
p、 axis.major\u标签\u文本\u font\u size=“9pt”
p、 轴长标签距离=0
p、 xaxis.major_标签_方向=1.0
#创建复选框选择元素
行=[“1”,“2”]
选择=复选框组(标签=行,
活动=[i代表范围内的i(0,len(行))])
callback=CustomJS(args=dict(source=source,savedsource=savedsource,plot=p),