Боке несоответствие фильтрации данных - PullRequest
0 голосов
/ 10 марта 2019

Извините, но я не могу сделать какой-либо воспроизводимый код для этого вопроса, так как он довольно противоречивый.

Итак, у меня есть таблица данных bokeh, и я делаю с ней фильтрацию, используя 4 выпадающих списка.Таблица данных обновляется на основе значения раскрывающегося списка, а обновления были написаны на JS.Фильтрация работает, как и ожидалось, но, как ни странно, для некоторых очень специфических комбинаций выпадающих значений она ничего не отображает в таблице данных.Мне было интересно, если это было проблемой с моими данными, но я привел все к строкам, и это все еще дало мне ту же проблему.

Обновления написаны здесь:

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 Ответ

1 голос
/ 14 марта 2019

Правильный способ обновления данных таблицы в вашем обратном вызове JS заключается в следующем:

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

Где source - это Bokeh ColumnDataSource вашей DataTable.Вам не нужно использовать:

source.change.emit();

Вы делаете это только тогда, когда вы заменяете только часть ваших данных, например, один столбец таблицы.И если data_table является вашим объектом Bokeh DataTable, пропустите также:

target_obj.change.emit();

Дата таблицы обновляется автоматически при обновлении ее ColumnDataSource.Посмотрите на этот простой пример:

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))
...