Python Боке - интерактивный сюжет с использованием виджета выбора и интерактивной легенды - пустой файл html - PullRequest
0 голосов
/ 26 мая 2020

У меня возникают некоторые проблемы при печати с боке. По категории есть фильтр, поэтому график должен обновляться при изменении. Также в сюжете есть интерактивная легенда.

Там должно быть что-то ломающееся с кодом. Я получаю сообщение об ошибке «BAD-COLUMN_NAME» в блокноте jupyter, но, вероятно, тоже есть проблемы, и файл html пуст. Пожалуйста, мне нужна помощь. Спасибо!

# Perform necessary imports
import pandas as pd
from bokeh.io import output_file, show
from bokeh.plotting import figure
from bokeh.models import CustomJS, HoverTool, ColumnDataSource, Select
from bokeh.palettes import Category20_20
from bokeh.layouts import layout, widgetbox, gridplot

#Dataframe
df = pd.DataFrame({'Reg': ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10'],
        'Category': ['Cat1', 'Cat1', 'Cat1', 'Cat2', 'Cat2', 'Cat2', 'Cat3', 'Cat3', 'Cat3', 'Cat3'],
        'X': ['751', '673', '542', '762', '624', '536', '845', '626', '876', '233'],
        'Y': ['458', '316', '287', '303', '297', '564', '278', '834', '234', '623'],
        'Size': ['5', '9', '5', '8', '10', '22', '23', '12', '9', '20'],           
        'User': ['u1', 'u2', 'u3', 'u1', 'u2', 'u3', 'u1', 'u2', 'u3', 'u3']           
        })

# Make the ColumnDataSource
source = ColumnDataSource(data=dict(Reg=df['Reg'], Category=df['Category'], x=df['X'], y=df['Y'], Size=df['Size'], User=df['User']))
filteredSource = ColumnDataSource(data=dict(Reg=[], Category=[], x=[], y=[], Size=[], User=[]))

#Create widget
category = list(set(df['Category']))
category.sort()
category_select = Select(title="Category:", value=category[0], options=category)

#Callback
callback = CustomJS(args=dict(source=source, filteredSource=filteredSource, 
                              category_select=category_select), code="""
    const data = source.data;
    var f = cb_obj.value;
    const df2 = filteredSource.data;
    df2['category']=[]

    for(i = 0; i < data['category'].length;i++){

    if(data['category'][i]==f){
        df2['category'].push(data['category'][i])
    }
    }

    filteredSource.change.emit()

""")

category_select.js_on_change('value', callback)

# Create the figure: p1
p1 = figure(x_axis_label='x)', y_axis_label='y', 
            plot_width=450, plot_height=450, tools=['box_select', HoverTool(tooltips='Size: @size')])
# Add a circle glyph to p1

users=list(set(df['User']))
for name, color in zip(users, Category20_20):
    user_df = df[df['User'] == name]
    p1.circle(x='X', y='Y', size='Size',
             color=color, alpha=0.8, source=filteredSource, legend=name)

p1.legend.location = "top_right"
p1.legend.click_policy="hide"

#layout
layout = gridplot([widgetbox(category_select), p1], ncols=2, sizing_mode='scale_both')
show(layout)

1 Ответ

1 голос
/ 26 мая 2020

У вас несоответствующий регистр символов в именах столбцов. Вы можете использовать, например, x и X. Вы должны придерживаться одного варианта и использовать его везде - в источниках данных, в спецификациях столбцов при создании средств визуализации глифов, в коде CustomJS и т.д.

Кроме того, ваш код CustomJS неверен . i = 0 приведет к ошибке - вместо него следует использовать let i = 0. И вы также обновляете только столбец Category, тогда как вам нужно обновить все столбцы, чтобы убедиться, что они имеют одинаковую длину.

В качестве примечания, судя по этому и другому вопросу, вы можете найти этот раздел документации весьма полезным: https://docs.bokeh.org/en/latest/docs/user_guide/data.html#filtering -data . Описанный здесь подход помогает предотвратить запись кода JS и ненужное перемешивание данных. Здесь и в Беседе Боке есть несколько примеров.

...