繁体   English   中英

如何在散景热图中删除/添加行并保持行高?

[英]How to delete/add rows in Bokeh heatmap and maintain row height?

我制作了一个 Bokeh 热图链接到 CheckBoxGroup,以便 CheckBoxGroup 中的活动项目对应于热图中显示的行。 即选中/取消选中 CheckBoxGroup 中的框会添加或删除热图中的行。 一切正常,除了我希望热图的行保持相同的高度,而不管热图中有多少行。 实际发生的是保留热图的原始高度,并调整行的大小以适应原始高度。

我在这里有一个 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)

我试过改变 plot.plot_height 和 plot.height_policy 但似乎都没有任何效果。

CustomJS回调的最后CustomJS行中,在update the yrange to reflect the deleted data注释之后,您明确更改了范围 - 这正是使绘图表现出其行为方式的原因。

只需删除source.data = newdata;之后的所有内容source.data = newdata; - 你不需要source.change.emit(); 要么因为您更改了整个数据属性。

这里需要的是在回调中调整frame_height并调用plot.properties.height.change.emit() - 从这里得到一些帮助回答: https : plot.properties.height.change.emit() 添加行散景热图和维护行高度/4917/10

最终 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)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM