Использование CustomJS для создания графика динамического рассеяния с Bokeh-Issue с ​​«несуществующим именем столбца» - PullRequest
0 голосов
/ 13 ноября 2018

Мне показалось, что я нашел конкретный пример того, как я могу использовать здесь , но, к сожалению, та же логика не работает для меня.

У меня два вопроса:

  • То, что я пытаюсь сделать, даже возможно: отправить динамический график рассеяния в html-документе, который позволяет вам контролировать то, что наносится на оси x & y.Я преуспел со статическими графиками, но еще не взломал динамические графики.

  • Где мой код работает неправильно (см. Ниже?)

Вот соответствующие фрагменты кода (по порядку. У меня есть фрейм данных, который я преобразовал в «источник» с помощью ColumnDataSource.

Я создаю начальный график (обратите внимание, на данный момент нетстолбцы с именами «x» и «y». Я создаю их в функции обратного вызова позже):

plot.circle('x', 'y',
            source=source,
            color={'field': 'Picker',
                    'transform': mapper},
                    legend='Picker')

Я создаю два раскрывающихся меню (обратите внимание, что параметры в каждом соответствуют столбцам из «источника» Iхотел бы, чтобы люди могли выбирать)

x_menu=Select(options=['Box Office', 'Difference', 'Price Paid'],
                        value='Box Office',
                         title='What do you want to put on the x axis')

y_menu=Select(options=['Metacritic', 'Rotten Tomatoes'],
                        value='Metacritic',
                         title='What do you want to put on the y axis')

Я создаю обратный вызов:

callback = CustomJS (args=dict(source=source), code="""
    console.log('changed selected option', cb_obj.value)
    var data=source.data
    data['x']=data[cb_obj.value]
    data['y']=data[cb_obj.value]
    source.change.emit();
    """)

Я назначаю обратные вызовы для выпадающих меню:

x_menu.callback = callback
y_menu.callback = callback

А потом я пытаюсь показать сюжет:

show(row(widgetbox(x_menu, y_menu), plot))

Но он возвращает ошибку ниже:

ERROR:bokeh.core.validation.check:E-1001 (BAD_COLUMN_NAME): Glyph refers to nonexistent column name: x, y [renderer: GlyphRenderer(id='df96b108-e2e4-4b8c-b0c6-12df40b4205d', ...)]

Любая помощь очень ценится. Спасибо!

1 Ответ

0 голосов
/ 14 ноября 2018

Было бы легче помочь, если бы вы дали самостоятельный минимальный пример (код, который мы можем просто скопировать, вставить и запустить). С учетом сказанного, вот кое-что, что может помочь вам начать. Вы уже были очень близки к этому решению, но я думаю, что важной частью является наличие одного обратного вызова для каждого меню.

Надеюсь, это поможет: -)

# -*- coding: utf-8 -*-
import numpy as np
import pandas as pd

from bokeh.layouts import row, widgetbox
from bokeh.models import CustomJS, Select
from bokeh.plotting import figure, show, ColumnDataSource

# Define some random data
dataframe = pd.DataFrame({
    'Difference': np.sin(np.linspace(0, 100, 500)),
    'Price': np.cos(np.linspace(0, 100, 500)),
    'Metacritic': np.sin(np.linspace(0, 100, 500)),
    'Rotten Tomatoes': np.cos(np.linspace(0, 200, 500)),
    })

# Set x and y-axis defaults
dataframe['x'] = dataframe['Difference']
dataframe['y'] = dataframe['Metacritic']

# Create Bokeh's ColumnDataSource
source = ColumnDataSource(data=dataframe)

# Create the plot figure
plot = figure(plot_width=400, plot_height=400)
plot.circle('x', 'y', source=source)

# Create the dropdown menus
x_menu = Select(options=['Difference', 'Price'],
                value='Difference',
                title='What do you want to put on the x axis')

y_menu = Select(options=['Metacritic', 'Rotten Tomatoes'],
                value='Metacritic',
                title='What do you want to put on the y axis')

# Create two callbacks, one for each menu
callback_x = CustomJS(args=dict(source=source), code="""
    console.log('changed selected option', cb_obj.value)
    var data=source.data
    data['x']=data[cb_obj.value]
    source.change.emit();
    """)

callback_y = CustomJS(args=dict(source=source), code="""
    console.log('changed selected option', cb_obj.value)
    var data=source.data
    data['y']=data[cb_obj.value]
    source.change.emit();
    """)

# Assign callbacks to menu widgets
x_menu.callback = callback_x
y_menu.callback = callback_y

# Show the html document with a layout
show(row(widgetbox(x_menu, y_menu), plot))
...