Я довольно новичок в bokeh и пытался взаимодействовать со своими построенными данными через виджеты Select и MultiSelect. Я заметил, что производительность значительно снижается, когда длинный аргумент (> 34 тыс. Элементов) предоставляется аргументу options для этих виджетов. Из того, что я видел, Select просто действует как mylist[mylist.index('selected_value')]
, а MultiSelect - как selected_vals.append(mylist[mylist.index('selected_value')])
, поэтому, если это действительно так, я не понимаю, почему виджеты так медленно возвращают свое значение, так как python может легко обрабатывать эти операции со списками. любой длины. Хотя я работаю с многомерными большими наборами данных, я уверен, что загруженные данные на самом деле не играют роли, так как я уже пытался отделить обновления графиков от виджетов и просто распечатать возвращенное значение, выбранное из выпадающего меню (это может занять до 30 секунд, и даже открытое меню может занять несколько секунд). Я попытался сократить список, переданный аргументу параметров (без изменения размера загружаемых данных), и виджеты ведут себя как ожидалось. Есть ли обходной путь / исправить это?
Вот часть кода
import numpy as np
import pandas as pd
from bokeh.layouts import row, column
from bokeh.models import Select, MultiSelect, ColumnDataSource, CDSView, GroupFilter
from bokeh.palettes import Viridis256
from bokeh.plotting import curdoc, figure
from bokeh.transform import log_cmap
data = np.random.rand(11000, 3)
normExpr = np.random.rand(11000, 35000)
gene_names = np.array(np.random.rand(35000), dtype='str')
clusters = list(np.array(range(20), dtype='str'))
normExpr = pd.DataFrame(normExpr, columns=gene_names)
data = pd.DataFrame(data, columns=['PHATE1', 'PHATE2', 'color'])
data['cluster'] = clusters*550
COLORS = Viridis256[::-1]
columns = list(gene_names)[:20]
def first_fig():
s = slice(len(data['color']))
source = ColumnDataSource(data)
kw = dict()
kw['title'] = "Expression of gene %s in %s" % (gene.value.title(), cluster.value.title())
p = figure(plot_height=500, plot_width=550, tools='pan,box_zoom,hover,reset',
toolbar_location="above", output_backend='webgl', **kw)
p.background_fill_color="#fafafa"
p.xaxis.axis_label = 'X-values'
p.yaxis.axis_label = 'Y-values'
if gene.value != 'None' and cluster.value != 'All tissue':
view = CDSView(source=source, filters=[GroupFilter(column_name='cluster', group=cluster.value)])
new = normExpr[gene.value]
source.patch({'color': [(s, new)]})
p.circle(x='PHATE1', y='PHATE2', source=source, view=view, radius=0.002, color=log_cmap('color', COLORS, 0, 1),
hover_color='white', hover_alpha=0.5)
elif gene.value == 'None' and cluster.value != 'All tissue':
view = CDSView(source=source, filters=[GroupFilter(column_name='cluster', group=cluster.value)])
p.circle(x='PHATE1', y='PHATE2', source=source, view=view, radius=0.002, color="#31AADE",
hover_color='white', hover_alpha=0.5)
elif gene.value != 'None' and cluster.value == 'All tissue':
new = normExpr[gene.value]
source.patch({'color': [(s, new)]})
p.circle(x='PHATE1', y='PHATE2', source=source, radius=0.002, color=log_cmap('color', COLORS, 0, 1),
hover_color='white', hover_alpha=0.5)
else:
p.circle(x='PHATE1', y='PHATE2', source=source, radius=0.002, color='#31AADE',
hover_color='white', hover_alpha=0.5)
return p
def update(attr, old, new):
layout.children[1] = first_fig()
cluster = Select(title='Cluster', value='All tissue', options=['All tissue'] + clusters)
cluster.on_change('value', update)
gene = Select(title='Gene', value='None', options=['None'] + columns)
gene.on_change('value', update)
controls = column([cluster, gene], width=100)
layout = row(controls, first_fig())
curdoc().add_root(layout)
curdoc().title = "Gene mapping"