создавать интерактивные сюжеты с боке python - PullRequest
0 голосов
/ 14 января 2020

Я хотел бы создать интерактивные сюжеты на одной фигуре с боке. Следующий код отлично работает для data_1, и, наконец, я получаю файл html:

data_1 = ColumnDataSource(data=user_id_weekly01)
data_2 = ColumnDataSource(data=user_id_weekly02)


output_file("test.html")
#generate info box with html
TOOLTIPS = """
<div style="background-color:  #8b85af">
    <div>
        <span style="font-size: 17px; font-weight: bold; user_ID:">user_ID: @user_ID</span>
    </div>
    <div>
        <span style="font-size: 17px; font-weight: bold; user_ID_count:">requested reports: @user_ID_count</span>
    </div>
    <div>
        <span style="font-size: 17px; font-weight: bold; number_requested_plots:">requested plots: @number_requested_plots</span>
    </div>
</div>
        """



p = figure(plot_width=1000, plot_height=500, tooltips=TOOLTIPS,
       title="test")
p.vbar(source=data_1,x='user_ID',top='user_ID_count',bottom=0,width=1.0)

p.y_range.start = 0
p.xaxis.axis_label = "user_ID"
p.yaxis.axis_label = "number requested report"
p.outline_line_color = None
p.xaxis.axis_label_text_font_size = "13pt"
p.yaxis.axis_label_text_font_size = "13pt"
p.xaxis.major_label_text_font_size = "13pt"
p.yaxis.major_label_text_font_size = "13pt"
p.title.text_font_size = '13pt'

show(p)

Теперь у меня есть не только data_1, но также data_2 и так далее. Я хотел бы построить что-то с помощью слайдера из боке, чтобы иметь возможность «скользить» по различным графикам. Если это не работает с ползунком, кнопка для нажатия была бы также разумным решением.

data_1 ect. looks like:
user_ID user_ID_count   number_requested_plots
0   13  1   19
1   28  1   8
2   53  3   57
3   64  8   145
4   82  1   11
5   94  1   19
6   100 13  228
7   102 1   19

Я с нетерпением жду некоторых советов, спасибо!

Ответы [ 2 ]

0 голосов
/ 20 января 2020

Я всегда go для сервера боке, если мне нужно создавать интерактивные графики. Преимущество: Вы можете написать собственный python код, не беспокоясь о JS обратных вызовах. Минимальный пример:

Обязательно запустите bokeh serve --show test.py из командной строки

# test.py
import numpy as np, pandas as pd
from bokeh.layouts import column, row
from bokeh.models import Slider,ColumnDataSource,TextInput
from bokeh.plotting import figure, curdoc

# Set up data
df1 = pd.DataFrame(np.random.randint(9,25,size=(2,2)),columns=["A","B"])
df2 = pd.DataFrame(np.arange(4,8).reshape(2,2),columns=["A","B"])
dfs = [df1,df2]
source = ColumnDataSource(df1)
# Set up plot
plot = figure(plot_height=400, plot_width=400, title="my source",x_range=[0,max(max(x["A"]) for x in dfs)+1],\
        y_range=[0,max(max(x["B"]) for x in dfs)+1])
plot.scatter("A","B", source = source)



# Set up widgets
text = TextInput(title="title", value='my source')
data = Slider(title="Choose Data",value=0, start=0, end=1)

# Set up callbacks

def update_title(attrname, old, new):
     plot.title.text = text.value

text.on_change('value', update_title)

def update_data(attrname, old, new):
    # Get the current slider values
    d = data.value

    # Generate new data
    if d == 0: source.data = df1
    if d == 1: source.data = df2


data.on_change("value",update_data)


# Set up layouts and add to document
inputs = column(data)

curdoc().add_root(row(inputs, plot))
curdoc().title = "my source"
0 голосов
/ 20 января 2020

Вы можете использовать Common JS и записывать обратный вызов при изменении значения ползунка (см. bokeh docs ). Например:

data_1 = ColumnDataSource(data=user_id_weekly01)
data_2 = ColumnDataSource(data=user_id_weekly02)
# add default source variable:
source = ColumnDataSource(data=user_id_weekly01)

# ...

# and use it in your vbar:
p.vbar(source=source,x='user_ID',top='user_ID_count',bottom=0,width=1.0)

# ...

# replace show(plt) with the following code:
from bokeh.models import Slider, CustomJS
from bokeh.layouts import column
datasources = [data_1, data_2]
slider  = Slider(start=0, end=len(datasources) -1, step=1, title="datasources", value=0)
callback = CustomJS(args=dict(source=source, datasources=datasources), code="""
        var i = cb_obj.value;
        source.data = Object.assign({},datasources[i].data);
        source.change.emit();
    """)
slider.js_on_change('value', callback)

show(column(p,slider))

Идея состоит в том, что при изменении значения ползунка вы заменяете исходные данные данными источника из списка источников данных.

...