In [7]:
from bokeh.io import output_file
output_file('/tmp/bokeh_notebook.html')
In [8]:
from pandas_datareader import wb
indicators_df = wb.get_indicators()
indicators_df['sourceOrganization'] = indicators_df['sourceOrganization'].str.decode("utf-8")
indicators_df.head()
Out[8]:
In [9]:
from bokeh.io import show, vform
from bokeh.models import ColumnDataSource, CustomJS
from bokeh.models.layouts import HBox
from bokeh.models.widgets import DataTable, TableColumn, StringFormatter, DateFormatter, Select
import pandas as pd
table_columns = [
TableColumn(field='id', title='ID'),
TableColumn(field='name', title='Name'),
TableColumn(field='source', title='Source'),
TableColumn(field='sourceNote', title='Source Note'),
TableColumn(field='sourceOrganization', title='Source Organization'),
TableColumn(field='topics', title='Topics'),
]
column_names = [tc.field for tc in table_columns]
table_source = ColumnDataSource(indicators_df[column_names])
data_table = DataTable(source=table_source, columns=table_columns, height=400, editable=False)
show(vform(data_table))
In [10]:
# two widgets
source_list = ['ALL'] + sorted(indicators_df['source'].unique().tolist())
source_select = Select(title="Source:", value=source_list[0], options=source_list)
topic_list = ['ALL'] + sorted(set([topic.strip() for topics in indicators_df['topics'].unique().tolist()
for topic in topics.split(';') if topic.strip()]))
topic_select = Select(title="Topic:", value=topic_list[0], options=topic_list)
# make a copy of the original data - "immutable"
original_table_source = ColumnDataSource(indicators_df[column_names])
arg_dct = dict(
source=table_source,
original_source=original_table_source,
source_select=source_select,
topic_select=topic_select,
target_obj=data_table
)
# filtering done in JS
callback_code = """
var data = source.get('data');
var original_data = original_source.get('data');
var source_name = source_select.get('value');
var topic_name = topic_select.get('value');
// now construct the new data object based on the filtered values
for (var key in original_data) {
data[key] = [];
for (var i = 0; i < original_data["id"].length; ++i) {
if ((source_name === "ALL" || original_data["source"][i] === source_name) &&
(topic_name === "ALL" || original_data["topics"][i].indexOf(topic_name) > -1)) {
data[key].push(original_data[key][i]);
}
}
}
target_obj.trigger('change');
source.trigger('change');
"""
generic_callback = CustomJS(args=arg_dct, code=callback_code)
source_select.callback = generic_callback
topic_select.callback = generic_callback
filter_widgets = HBox(children=[source_select, topic_select])
show(vform(filter_widgets, data_table))
In [11]:
from bokeh.models.widgets.tables import HTMLTemplateFormatter
try:
from urllib import quote
except ImportError as e:
from urllib.parse import quote
name_template_str = '<a target="_blank" href="<%= url %>"><%= value %></a>'
table_columns = [
TableColumn(field='id', title='ID'),
TableColumn(field='name', title='Name', formatter=HTMLTemplateFormatter(template=name_template_str)),
TableColumn(field='source', title='Source'),
TableColumn(field='sourceNote', title='Source Note'),
TableColumn(field='sourceOrganization', title='Source Organization'),
TableColumn(field='topics', title='Topics'),
]
column_names = [tc.field for tc in table_columns]
df = indicators_df.copy()
df['url'] = df['name'].apply(lambda s: 'http://search.worldbank.org/all?qterm={term}&language=EN'.format(term=quote(s)))
table_source = ColumnDataSource(df)
data_table = DataTable(source=table_source, columns=table_columns, height=400, editable=False)
show(vform(data_table))
In [ ]: