Bokeh datatable filtering inconsistency

纵然是瞬间 提交于 2020-01-24 00:59:30

问题


Apologies but I can't make any reproducible code for this question since it's pretty inconsistent.

So I have a bokeh data table, and I'm doing some filtering with it using 4 dropdown boxes. The data table updates based on dropdown box value, and the updates were written in JS. The filtering works as expected, but strangely enough for some very specific combinations of dropdown values it does not display anything in the data table. I was wondering if it was a problem with my data, but I coerced everything to strings and it still gave me the same problem.

The updates are written here:

combined_callback_code = """
var data = source.data;

var original_data = original_source.data;

var origin = origin_select_obj.value;

var classification = classification_select_obj.value;

var currency = currency_select_obj.value;

var grade = grade_select_obj.value;

for (var key in original_data) {
    data[key] = [];
    for (var i = 0; i < original_data['Origin'].length; ++i) {
        if ((origin === "ALL" || original_data['Origin'][i] === origin) &&
            (classification === "ALL" || original_data['Classification'][i] === classification) &&
            (currency === "ALL" || original_data['Currency'][i] === currency) &&
            (grade === "ALL" || original_data['BrokenPct'][i] === grade)){
            data[key].push(original_data[key][i]);
            }
    }
    }

target_obj.change.emit();
source.change.emit();
"""



# define the filter widgets, without callbacks for now
origin_list = ['ALL'] + df['Origin'].unique().tolist()
origin_select = Select(title="Origin:", value=origin_list[0], options=origin_list)

classification_list = ['ALL'] + df['Classification'].unique().tolist()
classification_select = Select(title="Classification:", value=classification_list[0], options=classification_list)

currency_list = ['ALL'] + df['Currency'].unique().tolist()
currency_select = Select(title = "Currency:", value=currency_list[0], options = currency_list)

grade_list = ["ALL"] + df['BrokenPct'].unique().tolist()
grade_select = Select(title = "Grade:", value = grade_list[0], options = grade_list)

# now define the callback objects now that the filter widgets exist
generic_callback = CustomJS(
    args=dict(source=source, 
              original_source=original_source, 
              origin_select_obj=origin_select, 
              classification_select_obj=classification_select,
              currency_select_obj = currency_select,
              grade_select_obj = grade_select,
              target_obj=data_table),
    code=combined_callback_code
)


# finally, connect the callbacks to the filter widgets
origin_select.js_on_change('value', generic_callback)
classification_select.js_on_change('value', generic_callback)
currency_select.js_on_change('value', generic_callback)
grade_select.js_on_change('value', generic_callback)

回答1:


The right way do update table data in your JS callback is this way:

var data = {};
//build your data here
source.data = data;

Where source is the Bokeh ColumnDataSource of you DataTable. You don't need to use:

source.change.emit();

You do it only when you replace only a part of you data e.g. one table column. And if data_table is your Bokeh DataTable object then also skip doing:

target_obj.change.emit();

The table date updates automatically when you update its ColumnDataSource. See this simple example:

from bokeh.io import show
from bokeh.layouts import widgetbox
from bokeh.models import ColumnDataSource, Slider, DataTable, TableColumn, CustomJS

source = ColumnDataSource(dict(x = list(range(6)), y = [x ** 2 for x in range(6)]))
columns = [TableColumn(field = "x", title = "x"), TableColumn(field = "y", title = "x**2")]
table = DataTable(source = source, columns = columns, width = 320)
slider = Slider(start = 1, end = 20, value = 6, step = 1, title = "i", width = 300)
callback_code = """ i = slider.value;
                    new_data = {"x": [1, 2, 3, 4, 5], "y": [1, 4, 9, 16, 25]}
                    table.source.data = new_data
                    table.width = 320 + i * 25;  """
callback = CustomJS(args = dict(slider = slider, table = table), code = callback_code)
slider.js_on_change('value', callback)
show(widgetbox(slider, table))


来源:https://stackoverflow.com/questions/55089115/bokeh-datatable-filtering-inconsistency

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!