简体   繁体   中英

Select rows from ColumnDataSource in Bokeh interactive line plot

I am stuck trying to select rows to plot in a simple Bokeh line plot. The desired result is a simple line plot with Date on the x-axis and Value on the y-axis. Using 2 select widgets I would like to select Country and Type .

Any suggestions a more than welcome!

My code so far:

import pandas as pd
import numpy as np
from bokeh.models.widgets import Select
from bokeh.models import ColumnDataSource, Select, CDSView, GroupFilter
from bokeh.io import show, output_notebook
from bokeh.plotting import figure

output_notebook()

# base
df = pd.DataFrame({'Country': ['A', 'A', 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'B', 'B'],
                   'Date': ['01-01-2020', '01-02-2020', '01-03-2020', '01-01-2020', '01-02-2020', '01-03-2020', '01-01-2020', '01-02-2020', '01-03-2020', '01-01-2020', '01-02-2020', '01-03-2020'],
                   'Type': ['X', 'X', 'X', 'Y', 'Y', 'Y', 'X', 'X', 'X', 'Y', 'Y', 'Y'],
                   'Value': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]})
df['Date'] = pd.to_datetime(df['Date'])

source = ColumnDataSource(df)

country_filter = CDSView(source=source, filters=[GroupFilter(column_name='Country', group='A')])
type_filter = CDSView(source=source, filters=[GroupFilter(column_name='Type', group='X')])

country_select = Select(title="Country:", value="A", options=np.unique(source.data['Country']).tolist())
country_select.js_link('value', country_filter, 'group')

type_select = Select(title="Type:", value="X", options=np.unique(source.data['Type']).tolist())
type_select.js_link('value', type_filter, 'group')

p = figure()
p.line(x='Date', y='Value', source=source, view=view)

layout = row(p, column(country_select, type_select))

show(layout)

You almost got it. Here's a working version. Two things to note:

  1. I had to manually link group filters' changes to the view's change signal - right now Bokeh doesn't make that link internally
  2. Since you're using lines, this code will produce a warning about using filters with glyphs with connected topology. It can safely be ignored in your case
import numpy as np
import pandas as pd
from bokeh.io import show
from bokeh.layouts import row, column
from bokeh.models import ColumnDataSource, Select, CDSView, GroupFilter, CustomJS
from bokeh.plotting import figure

df = pd.DataFrame({'Country': ['A', 'A', 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'B', 'B'],
                   'Date': ['01-01-2020', '01-02-2020', '01-03-2020', '01-01-2020', '01-02-2020', '01-03-2020',
                            '01-01-2020', '01-02-2020', '01-03-2020', '01-01-2020', '01-02-2020', '01-03-2020'],
                   'Type': ['X', 'X', 'X', 'Y', 'Y', 'Y', 'X', 'X', 'X', 'Y', 'Y', 'Y'],
                   'Value': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]})
df['Date'] = pd.to_datetime(df['Date'])

source = ColumnDataSource(df)

country_filter = GroupFilter(column_name='Country', group='A')
type_filter = GroupFilter(column_name='Type', group='X')
view = CDSView(source=source, filters=[country_filter, type_filter])

# Alas, we need this manual step to make the view know about the filters' changes.
for f in view.filters:
    f.js_on_change('group', CustomJS(args=dict(view=view),
                                     code="view.properties.filters.change.emit();"))

country_select = Select(title="Country:", value="A", options=np.unique(source.data['Country']).tolist())
country_select.js_link('value', country_filter, 'group')

type_select = Select(title="Type:", value="X", options=np.unique(source.data['Type']).tolist())
type_select.js_link('value', type_filter, 'group')

p = figure()
p.line(x='Date', y='Value', source=source, view=view)

show(row(p, column(country_select, type_select)))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM