Основываясь на ответе Тони (используя BoxSelectTool для одиночного выбора), я придумал код для множественного выбора. (Обратите внимание, что я сделал несколько опечаток в моей первоначальной функции callback1)
from bokeh.plotting import figure, show
from bokeh.layouts import gridplot
from bokeh.models import ColumnDataSource, CDSView, BooleanFilter, CustomJS, BoxSelectTool
import pandas as pd
# output_notebook()
data = {'person': [1, 1, 1, 2, 2, 3, 3, 3, 3],
'activities':['a', 'b', 'c', 'a', 'b', 'a', 'b', 'c', 'd'],
'hours':[3, 4, 6, 2, 7, 5, 3, 2, 12],
'foodeaten':[12, 14, 34, 45, 67, 5, -1, 3, 5]}
df = pd.DataFrame(data = data)
print(df)
source = ColumnDataSource(data = df)
views = [(df.activities == l) for l in ['a', 'b', 'c', 'd']]
filtered_views = [CDSView(source = source, filters = [BooleanFilter(view.values.tolist())]) for view in views]
plot_options = dict(plot_width = 250,
plot_height = 250,
tools = "box_select,tap,pan,wheel_zoom,reset,save",
tooltips = [("Person", "@person"), ("hours", "@hours")])
plots = [figure(title = 'activity {l}'.format(l = l), **plot_options) for l in ['a', 'b', 'c', 'd', 'a', 'b', 'c', 'd']]
for plot, view, name in zip(plots, 2 * filtered_views, 4 * ['hours'] + 4 * ['foodeaten']):
plot.circle('person', y = name, size = 15, view = view, source = source)
callback1 = CustomJS(args = dict(source = source, ), code = """
var selected_indices = source.selected.indices;
var data = source.data;
debugger;
console.log(selected_indices)
var all_selected = [];
var persons = [];
for (i in selected_indices){
index = selected_indices[i];
console.log(data['person'][index]);
persons.push(data['person'][index]);
}
for (i in data.index){
index = data.index[i]
for (j in persons){
person = persons[j]
if (data['person'][i] == person){
all_selected.push(index);
}
}
}
source.selected.indices=all_selected;
""")
# output_file('testSelect.html')
for plot in plots:
plot.select(BoxSelectTool).callback = callback1
show(gridplot(children = [plot for plot in plots], ncols = 2))
Прочитайте эту статью.
Быть педантичным: for_each
операция последовательности неизменения. Намерение не состоит в том, чтобы изменить последовательность. Однако это должно хорошо изменить входную последовательность при использовании for_each
.
Если в сомнении используют станд.:: преобразуйте, поскольку это передаст даже случайному читателю Вашего кода, что Вы намереваетесь изменить что-то.
Вы неправильно понимаете что-то. Входные итераторы высказывания, как только гарантируют, будут применимы, поскольку rvalues не означает, что Вы не можете вытащить lvalue из итератора так или иначе. Таким образом, это не означает что результат *iterator
rvalue. Чему передает you/for_each AddOne
результат operator*
- не сам итератор.
О нас for_each
и функциональный объект изменения - считал этот вопрос
Это законно - входные итераторы используются, чтобы указать диапазон, не сделать обработку.
Интересно, Josuttis в его книге "списки" Библиотеки Стандарта C++ for_each
как изменение, raher, чем неизменение.