Используйте Bokeh RadioGroup для построения выбранного подмножества Pandas DataFrame в Jupyter - PullRequest
0 голосов
/ 08 мая 2020

Цель

Постройте подмножества строк в Pandas DataFrame, выбрав заданное c значение столбца.

Идеально построить его в блокноте jupyter.

Что я сделал

У меня минимальные знания Javascript, поэтому мне удалось построить график, запустив сервер Bokeh со всем, что написано в Python.

Однако я не смог сделать это в блокноте Jupyter с обратным вызовом Javascript. Мой способ сделать это звучит немного глупо: разбивая DataFrame на подмножества по значениям столбца и помещая их в dict, я могу выбрать подмножество с помощью активного выбора из RadioGroup.

Это мой пример кода:


import pandas as pd
import bokeh
from bokeh.io import output_notebook, show
import bokeh.plotting as bp
import bokeh.models as bm
from bokeh.layouts import column, row

data = {
    'Datetime': ['2020-04-09T10:23:38Z', '2020-04-09T22:23:38Z','2020-04-09T23:23:38Z', '2020-01-09T10:23:38Z', '2020-01-09T22:23:38Z', '2020-01-09T23:23:38Z'],
    'Month': ['Apr', 'Apr', 'Apr', 'Jan', 'Jan', 'Jan'],
    'Values': [1.2, 1.3, 1.5, 1.1, 3, 1.3]
}

df = pd.DataFrame.from_dict(data)
month_list = df['Month'].unique().tolist()

plot_height = 600
plot_width = 1000
col2plot = 'Values'

month_dict = {}
for m in month_list:
    subset = df[df['Month'] == m].reset_index(drop=True)
    month_dict[m] = subset[['Datetime', col2plot]].to_dict()

p1 = bp.figure(
    plot_height=plot_height, 
    plot_width=plot_width, 
    title='Values',
    toolbar_location=None,
    tools="hover",
    tooltips=[("DateTime", "@Datetime")]
)

src = bm.ColumnDataSource(df[df['Month'] == 'Jan'].reset_index(drop=True))
p1.line(x='index', y=col2plot, alpha=0.8, source=src)

month_selector = bm.widgets.RadioGroup(labels=month_list, active=1)

jscode = """
var month = cb_obj.labels[cb_obj.active] //selected month
const new_data = source[month]
src.data = new_data
src.change.omit()
"""
callback = bm.CustomJS(args=dict(src=src, source=month_dict), code=jscode)
month_selector.js_on_change('active', callback)
output_notebook()
show(row(p1, month_selector))

Код работает, но при выборе определенного месяца график не обновляется. Вероятно, это из-за плохой обработки обратного вызова JS, есть идеи по исправлению этого? Большое спасибо за вашу помощь!

1 Ответ

0 голосов
/ 08 мая 2020

Проблемы с вашим кодом:

  • В p.line вы используете столбец index. Но когда вы звоните pd.DataFrame.to_dict(), столбца там нет. Может быть исправлено добавлением еще одного .reset_index() перед .to_dict()
  • to_dict() возвращает данные в виде dict of dicts, но ColumnDataSource требует dict списков. Замените звонок на to_dict('list')
  • src.change.omit() - здесь опечатка, должно быть emit. Но поскольку вы заменяете весь атрибут data вместо того, чтобы просто изменять некоторые данные, вы можете просто полностью удалить строку
...