Bokeh: DataTable - how to set selected rows - python

I would like to change the DataTable object row selection programmatically (without JS, just python). I have tried to so using the selected property of the underlying ColumnsSource with no success. How can this be done?

See an example app (needs bokeh serve to run) where pressing the button changes the selected rows, then updates both a table and plot. Is this all the functionality you need?
By the way you could just do it in JS and not need to use bokeh server, but if you have more python functionality going on then i guess you need it.
from datetime import date
from random import randint
from bokeh.io import output_file, show, curdoc
from bokeh.plotting import figure
from bokeh.layouts import widgetbox, row
from bokeh.models import ColumnDataSource
from bokeh.models.widgets import DataTable, DateFormatter, TableColumn,Button
output_file("data_table.html")
data = dict(
dates=[date(2014, 3, i+1) for i in range(10)],
downloads=[randint(0, 100) for i in range(10)],
)
def update():
#set inds to be selected
inds = [1,2,3,4]
source.selected = {'0d': {'glyph': None, 'indices': []},
'1d': {'indices': inds}, '2d': {}}
# set plot data
plot_dates = [data['dates'][i] for i in inds]
plot_downloads = [data['downloads'][i] for i in inds]
plot_source.data['dates'] = plot_dates
plot_source.data['downloads'] = plot_downloads
source = ColumnDataSource(data)
plot_source = ColumnDataSource({'dates':[],'downloads':[]})
table_button = Button(label="Press to set", button_type="success")
table_button.on_click(update)
columns = [
TableColumn(field="dates", title="Date", formatter=DateFormatter()),
TableColumn(field="downloads", title="Downloads"),
]
data_table = DataTable(source=source, columns=columns, width=400, height=280)
p = figure(plot_width=400, plot_height=400)
# add a circle renderer with a size, color, and alpha
p.circle('dates','downloads',source=plot_source, size=20, color="navy", alpha=0.5)
curdoc().add_root(row([table_button,data_table,p]))

You can select DataTable rows programmatically in python in this way:
source.selected.indices = [list of indices to be selected]
where source is the ColumnDataSource for the DataTable. If you have any callbacks for the source.selected here, remember to select the rows only after registering the callbacks so that they will get called.

Just for clarity you have to replace the source.selected property completely to trigger the changes. So the important line is:
source.selected = {'0d': {'glyph': None, 'indices': []},
'1d': {'indices': inds}, '2d': {}}
Individually setting the items in source.selected doesn't work
source.selected['1d']['indices'] = inds # Doesn't work

Related

How to use bokeh select element to make sliders hide or invisible?

This sample is altered from the bokeh example, sliders can control the bars in the figure. (sliders.py)
This sample is altered from the bokeh example, sliders can control the bars in the figure. (sliders.py)
In my situation, there are more than 30 sliders on the left. It seems a little messy, so I am trying to use bokeh select element to connect sliders. The aim is the slider area will show only one slider when I select.
I read the document, and there are two ways to use:
One is disabled. If True, the widget will be greyed-out and not responsive to UI events. But it would not hide. Another is visible, but I got an attribute error:
AttributeError("unexpected attribute 'visible' to Slider, similar attributes are disabled")
Is it possible to make bokeh sliders hide or invisible? Or is there any other way to make sliders (more than 30) distinguish more clearly?
Here is the code which can run in Jupyter notebook
import bokeh.plotting.figure as bk_figure
from bokeh.io import curdoc, show
from bokeh.layouts import row, widgetbox
from bokeh.models import ColumnDataSource, Select
from bokeh.models.widgets import Slider, TextInput
from bokeh.io import output_notebook # enables plot interface in J notebook
import numpy as np
# init bokeh
from bokeh.application import Application
from bokeh.application.handlers import FunctionHandler
output_notebook()
# Set up data
data = {
'line_x' : [1,2,3,4],
'line_y' : [4,3,2,1],
'bar_x':[1, 2, 3, 4],
'bar_bottom':[1,1,1,1],
'bar_top':[0.2, 2.5, 3.7, 4],
}
#bar_color
determine_top = data['bar_top']
determine_bottom = data['bar_bottom']
determine_color = []
for i in range(0,4):
if (determine_top[i] > determine_bottom[i]):
determine_color.append('#B3DE69') #green
else:
determine_color.append('firebrick')
i+=1
data['determine_colors'] = determine_color
source = ColumnDataSource(data=data)
# Set up plot
plot = bk_figure(plot_height=400, plot_width=400, title="test",
tools="crosshair,pan,reset,save,wheel_zoom",
x_range=[0, 10], y_range=[-5, 5])
plot.vbar(x='bar_x', width=0.5, top='bar_top',bottom='bar_bottom',
source=source, color='determine_colors')
# Set up widgets
select = Select(title="days_select:",
options=["d1_select", "d2_select", "d3_select", "d4_select"])
d1 = Slider(title="d1", value=0.0, start=-5.0, end=5.0, step=0.1)
d2 = Slider(title="d2", value=1.0, start=-5.0, end=5.0, step=0.1)
d3 = Slider(title="d3", value=0.0, start=0.0, end=2*np.pi)
d4 = Slider(title="d4", value=1.0, start=0.1, end=5.1, step=0.1)
# Set up callbacks
def update_data(attrname, old, new):
# Get the current slider values
d1_value = d1.value
d2_value = d2.value
d3_value = d3.value
d4_value = d4.value
##select
#if select.value == "d2_select":
# d3.disabled = True
# d4.visible = False
# Generate the new curve
new_data = {
'line_x' : [1,2,3,4],
'line_y' : [4,3,2,1],
'bar_x': [1, 2, 3, 4],
'bar_bottom':[d1_value, d2_value, d3_value, d4_value],
'bar_top':[0.2, d1_value, d2_value, d3_value],
}
#bar_color
determine_top = new_data['bar_top']
determine_bottom = new_data['bar_bottom']
determine_color = []
for i in range(0,4):
if (determine_top[i] > determine_bottom[i]):
determine_color.append('green') #green
else:
determine_color.append('red')
i+=1
new_data['determine_colors'] = determine_color
source.data = new_data
for w in [select, d1, d2, d3, d4]:
w.on_change('value', update_data)
# Set up layouts and add to document
layout = row(widgetbox(select, d1, d2, d3, d4), plot)
def modify_doc(doc):
doc.add_root(row(layout, width=800))
doc.title = "Sliders"
handler = FunctionHandler(modify_doc)
app = Application(handler)
show(app)
Thanks for any suggestions.

Updating plot using Select Widget issue

I am currently trying to write a program that will switch between two sets of data when different options are chosen from the select widget. I am trying to make this program as autonomous as possible so in the future when people update the data they don't have to modify the code at all and the updates will happen automatically.
Currently, my issue is that when I select 'White' I want the plot to update but nothing is happening.
The two data sets are currently a dict of lists, one labeled 'White_dict' and the other labeled 'black_dict' solely to represent the color of the material for the data (I know its kinda ironic).
from bokeh.plotting import figure, curdoc
from bokeh.models import ColumnDataSource, Legend
from bokeh.models import Select
from bokeh.layouts import column
import pandas as pd
from plot_tools import add_hover
import itertools
from collections import defaultdict
bokeh_doc = curdoc()
material_types = pd.read_csv('data/material-information.csv')
df = pd.read_csv('data/Black_Materials_total_reflecatance.csv')
black_df = pd.read_csv('data/Black_Materials_total_reflecatance.csv')
white_df = pd.read_csv('data/SPIE18_white_all.csv')
names = []
w_names = []
black_dict = defaultdict(list)
white_dict = defaultdict(list)
for name, w_name in zip(df, white_df):
names.append(name)
w_names.append(w_name)
data = pd.read_csv('data/Black_Materials_total_reflecatance.csv', usecols = names)
w_data = pd.read_csv('data/SPIE18_white_all.csv', usecols = w_names)
for name, w_name in zip(names, w_names):
for i in range(0, 2250):
black_dict[name].append(data[name][i])
white_dict[w_name].append(w_data[w_name][i])
mySource = ColumnDataSource(data = black_dict)
#create total reflectance figure
total_fig = figure(plot_width = 650, plot_height = 350,
title = 'Total Reflectance',
x_axis_label = 'Wavelength(nm)', y_axis_label = 'Total Reflectance',
x_range = (250, 2500), y_range = (0,10),
title_location = 'above', sizing_mode = "scale_both",
toolbar_location = "below",
tools = "box_zoom, pan, wheel_zoom, save")
select = Select(title="Material Type", options=['Black', 'White'])
def update_plot(attr, old, new):
if new == 'White':
mySource.data = white_dict
else:
mySource.data = black_dict
for name, color in zip(mySource.data, Turbo256):
if name != 'nm':
total_fig.line('nm', name, line_width = .7, source = mySource, color = color)
select.on_change('value', update_plot)
bokeh_doc.add_root(total_fig)
bokeh_doc.add_root(select)
I'm currently using bokeh serve bokehWork.py to launch the server. If anyone has any idea on what I should fix it would be much appreciated! Thanks!
EDIT:
Adding data for Black_materials_total_reflectance.csv
Black Reflectance Data sample
Adding data for White_all.csv
White Reflectance Data sample
There are two main issues with your code:
You read the same files multiple times and you do a lot of work that Pandas and Bokeh can already do for you
(the main one) You do not take into account the fact that different CSV files have different column names
Here's a fixed version. Notice also the usage of the palette. With just Turbo256 you were getting almost the same color for all lines.
import pandas as pd
from bokeh.models import ColumnDataSource, Select
from bokeh.palettes import turbo
from bokeh.plotting import figure, curdoc
black_ds = ColumnDataSource(pd.read_csv('/home/p-himik/Downloads/Black_material_data - Sheet1.csv').set_index('nm'))
white_ds = ColumnDataSource(pd.read_csv('/home/p-himik/Downloads/White Materials Sample - Sheet1.csv').set_index('nm'))
total_fig = figure(plot_width=650, plot_height=350,
title='Total Reflectance',
x_axis_label='Wavelength(nm)', y_axis_label='Total Reflectance',
title_location='above', sizing_mode="scale_both",
toolbar_location="below",
tools="box_zoom, pan, wheel_zoom, save")
total_fig.x_range.range_padding = 0
total_fig.x_range.only_visible = True
total_fig.y_range.only_visible = True
palette = turbo(len(black_ds.data) + len(white_ds.data))
def plot_lines(ds, color_offset, visible):
renderers = []
for name, color in zip(ds.data, palette[color_offset:]):
if name != 'nm':
r = total_fig.line('nm', name, line_width=.7, color=color,
source=ds, visible=visible)
renderers.append(r)
return renderers
black_renderers = plot_lines(black_ds, 0, True)
white_renderers = plot_lines(white_ds, len(black_ds.data), False)
select = Select(title="Material Type", options=['Black', 'White'], value='Black')
def update_plot(attr, old, new):
wv = new == 'White'
for r in white_renderers:
r.visible = wv
for r in black_renderers:
r.visible = not wv
select.on_change('value', update_plot)
bokeh_doc = curdoc()
bokeh_doc.add_root(total_fig)
bokeh_doc.add_root(select)

local variable df referenced before assignment (Bokeh Interactive Visualization)

I just need a dropdown menu that shows all the departments and when we update the department it should generate the bar graph that gives all the products and it's corresponding retail value.
But it's giving a box with no visualization and a dropdown list.
Error: "local variable 'df' referenced before assignment"
import numpy as np
import pandas as pd
import os
import math
from bokeh.io import show, output_file
from bokeh.plotting import figure
from bokeh.transform import factor_cmap
from bokeh.models import ColumnDataSource, HoverTool, CustomJS
from bokeh.layouts import row, column
from bokeh.models.widgets import Dropdown
from bokeh.io import curdoc
df = pd.read_csv('/Users/austinejose/Desktop/My Files/Work/Newcastle Service Station/2018/Feb_Totals.csv')
source = ColumnDataSource(data=df)
names = [str(x) for x in df['Product Name']]
plot = figure(x_range = 'Product Name', plot_height = 500, width = 700, title = "Sales By Departments",
toolbar_location = "below")
plot.vbar(x = "Product Name", top = "Retail Value", width = 0.9, source = source, color = 'deepskyblue')
plot.xgrid.grid_line_color = "white"
plot.y_range.start = 0
plot.xaxis.major_label_orientation = math.pi/4
plot.xaxis.axis_label = "Product"
plot.yaxis.axis_label = "Retail Value"
plot.axis.minor_tick_in = -3
plot.axis.minor_tick_out = 6
plot.outline_line_color = "black"
menu = [("Bill Pay", "Bill Pay"), ("Hot Food", "Hot Food")]
menu_select = Dropdown(label='Department' ,menu=menu)
def dropdown_click(attr, old, new):
active_dropdown = menu_select.value
if active_dropdown in df['Department']:
df = df[df['Department']==active_dropdown]
source.data = df
menu_select.on_change('value', dropdown_click)
layout = row(menu_select, plot)
curdoc().add_root(layout)
You have a logic error in your callback:
def dropdown_click(attr, old, new):
active_dropdown = menu_select.value
if active_dropdown in df['Department']:
df = df[df['Department']==active_dropdown]
source.data = df
If active_dropdown in df['Department'] is False, then your code never defines df before trying to set source.data = df. This is the immediate cause of the message Error: "local variable 'df' referenced before assignment".
One possible solution is to move the assignment inside the if block, so that the assignment only ever happens when df is guaranteed to exist. Otherwise, you need to figure out what you want to heppen when the condition is False.
However, there is also a Bokeh usage error you will need to fix as well. The value of source.data has to be a plain Python dict, not a Pandas DataFrame.

Python bokeh slider not refreshing plot

I am creating a bokeh plot with a slider to refresh plot accordingly. There are 2 issues with the code posted.
1. The plot is not refreshed as per the slider. Please help in providing a fix for this issue.
2. Plot is not displayed with curdoc() when bokeh serve --show fn.ipynb is used
I'm trying to visualise this CSV file.
import pandas as pd
import numpy as np
from bokeh.models import ColumnDataSource, CategoricalColorMapper, HoverTool, Slider
from bokeh.plotting import figure, curdoc
from bokeh.palettes import viridis
from bokeh.layouts import row, widgetbox
#Importing and processing data file
crop = pd.read_csv('crop_production.csv')
#Cleaning Data
crop.fillna(np.NaN)
crop['Season'] = crop.Season.str.strip()
#Removing Whitespace #Filtering the dataset by Season
crop_season = crop[crop.Season == 'Whole Year']
crop_dt = crop_season.groupby(['State_Name', 'District_Name', 'Crop_Year']).mean().round(1)
#Creating Column Data Source
source = ColumnDataSource({
'x' : crop_dt[crop_dt.index.get_level_values('Year')==2001].loc[(['ABC']), :].Area,
'y' : crop_dt[crop_dt.index.get_level_values('Year')==2001].loc[(['ABC']), :].Production,
'state' : crop_dt[crop_dt.index.get_level_values('Year')==2001].loc[(['ABC']), :].index.get_level_values('State_Name'),
'district' : crop_dt[crop_dt.index.get_level_values('Year')==2001].loc[(['ABC']), :].index.get_level_values('District_Name')
})
#Creating color palette for plot
district_list = crop_dt.loc[(['Tamil Nadu']), :].index.get_level_values('District_Name').unique().tolist()
call_colors = viridis(len(district_list))
color_mapper = CategoricalColorMapper(factors=district_list, palette=call_colors)
# Creating the figure
#xmin, xmax = min(data.Crop_Year), max(data.Crop_Year)
#ymin, ymax = min(data.Production), max(data.Production)
p = figure(
title = 'Crop Area vs Production',
x_axis_label = 'Area',
y_axis_label = 'Production',
plot_height=900,
plot_width=1200,
tools = [HoverTool(tooltips='#district')]
)
p.circle(x='x', y='y', source=source, size=12, alpha=0.7,
color=dict(field='district', transform=color_mapper),
legend='district')
p.legend.location = 'top_right'
def update_plot(attr, old, new):
yr = slider.value
new_data = {
'x' : crop_dt[crop_dt.index.get_level_values('Year')==yr].loc[(['ABC']), :].Area,
'y' : crop_dt[crop_dt.index.get_level_values('Year')==yr].loc[(['ABC']), :].Production,
'state' : crop_dt[crop_dt.index.get_level_values('Year')==yr].loc[(['ABC']), :].index.get_level_values('State_Name'),
'district' : crop_dt[crop_dt.index.get_level_values('Year')==yr].loc[(['ABC']), :].index.get_level_values('District_Name')
}
source.data = new_data
#Creating Slider for Year
start_yr = min(crop_dt.index.get_level_values('Crop_Year'))
end_yr = max(crop_dt.index.get_level_values('Crop_Year'))
slider = Slider(start=start_yr, end=end_yr, step=1, value=start_yr, title='Year')
slider.on_change('value',update_plot)
layout = row(widgetbox(slider), p)
curdoc().add_root(layout)
show(layout)
Also tried a different option using CustomJS as below, but still no luck.
callback = CustomJS(args=dict(source=source), code="""
var data = source.data;
var yr = slider.value;
var x = data['x']
var y = data['y']
'x' = crop_dt[crop_dt.index.get_level_values('Crop_Year')==yr].loc[(['ABC']), :].Area;
'y' = crop_dt[crop_dt.index.get_level_values('Crop_Year')==yr].loc[(['ABC']), :].Production;
p.circle(x='x', y='y', source=source, size=12, alpha=0.7,
color=dict(field='district', transform=color_mapper),
legend='district');
}
source.change.emit();
""")
#Creating Slider for Year
start_yr = min(crop_dt.index.get_level_values('Crop_Year'))
end_yr = max(crop_dt.index.get_level_values('Crop_Year'))
yr_slider = Slider(start=start_yr, end=end_yr, step=1, value=start_yr, title='Year', callback=callback)
callback.args["slider"] = yr_slider
Had a lot of issues trying to execute your code and I have changed some things, so feel free to correct me if did something wrong.
The error was caused by the creation of the ColumnDataSource, I had to change the level value to Crop_Year instead of Year. The loc 'ABC' also caused an error so I removed that too (And I had to add source = ColumnDataSource({, you probably forgot to copy that)
I also added a dropdown menu so it's possible to only show the data from one district.
Also, I'm not quite sure if it's possible to start a bokeh server by supplying a .ipynb file to --serve. But don't pin me down on that, I never use notebooks. I've tested this with a .py file.
#!/usr/bin/python3
import pandas as pd
import numpy as np
from bokeh.models import ColumnDataSource, CategoricalColorMapper, HoverTool
from bokeh.plotting import figure, curdoc
from bokeh.palettes import viridis
from bokeh.layouts import row, widgetbox
from bokeh.models.widgets import Select, Slider
#Importing and processing data file
crop = pd.read_csv('crop_production.csv')
#Cleaning Data
crop.fillna(np.NaN)
crop['Season'] = crop.Season.str.strip()
#Removing Whitespace #Filtering the dataset by Season
crop_season = crop[crop.Season == 'Whole Year']
crop_dt = crop_season.groupby(['State_Name', 'District_Name', 'Crop_Year']).mean().round(1)
crop_dt_year = crop_dt[crop_dt.index.get_level_values('Crop_Year')==2001]
crop_dt_year_state = crop_dt_year[crop_dt_year.index.get_level_values('State_Name')=='Tamil Nadu']
#Creating Column Data Source
source = ColumnDataSource({
'x': crop_dt_year_state.Area.tolist(),
'y': crop_dt_year_state.Production.tolist(),
'state': crop_dt_year_state.index.get_level_values('State_Name').tolist(),
'district': crop_dt_year_state.index.get_level_values('District_Name').tolist()
})
#Creating color palette for plot
district_list = crop_dt.loc[(['Tamil Nadu']), :].index.get_level_values('District_Name').unique().tolist()
call_colors = viridis(len(district_list))
color_mapper = CategoricalColorMapper(factors=district_list, palette=call_colors)
# Creating the figure
p = figure(
title = 'Crop Area vs Production',
x_axis_label = 'Area',
y_axis_label = 'Production',
plot_height=900,
plot_width=1200,
tools = [HoverTool(tooltips='#district')]
)
glyphs = p.circle(x='x', y='y', source=source, size=12, alpha=0.7,
color=dict(field='district', transform=color_mapper),
legend='district')
p.legend.location = 'top_right'
def update_plot(attr, old, new):
#Update glyph locations
yr = slider.value
state = select.value
crop_dt_year = crop_dt[crop_dt.index.get_level_values('Crop_Year')==yr]
crop_dt_year_state = crop_dt_year[crop_dt_year.index.get_level_values('State_Name')==state]
new_data = {
'x': crop_dt_year_state.Area.tolist(),
'y': crop_dt_year_state.Production.tolist(),
'state': crop_dt_year_state.index.get_level_values('State_Name').tolist(),
'district': crop_dt_year_state.index.get_level_values('District_Name').tolist()
}
source.data = new_data
#Update colors
district_list = crop_dt.loc[([state]), :].index.get_level_values('District_Name').unique().tolist()
call_colors = viridis(len(district_list))
color_mapper = CategoricalColorMapper(factors=district_list, palette=call_colors)
glyphs.glyph.fill_color = dict(field='district', transform=color_mapper)
glyphs.glyph.line_color = dict(field='district', transform=color_mapper)
#Creating Slider for Year
start_yr = min(crop_dt.index.get_level_values('Crop_Year'))
end_yr = max(crop_dt.index.get_level_values('Crop_Year'))
slider = Slider(start=start_yr, end=end_yr, step=1, value=start_yr, title='Year')
slider.on_change('value',update_plot)
#Creating drop down for state
options = list(set(crop_dt.index.get_level_values('State_Name').tolist()))
options.sort()
select = Select(title="State:", value="Tamil Nadu", options=options)
select.on_change('value', update_plot)
layout = row(widgetbox(slider, select), p)
curdoc().add_root(layout)
#Jasper Thanks a lot. This works, however it doesnt work with .loc[(['Tamil Nadu']), :]. Reason for having this is to filter the data by adding a bokeh dropdown or radio button object and refresh the plot based on the filters. The below code works only if .loc[(['Tamil Nadu']), :] is removed. Is there any other way to fix this please?
def update_plot(attr, old, new):
yr = slider.value
new_data = {
'x' : crop_dt[crop_dt.index.get_level_values('Crop_Year')==yr].loc[(['Tamil Nadu']), :].Area.tolist(),
'y' : crop_dt[crop_dt.index.get_level_values('Crop_Year')==yr].loc[(['Tamil Nadu']), :].Production.tolist(),
'state' : crop_dt[crop_dt.index.get_level_values('Crop_Year')==yr].loc[(['Tamil Nadu']), :].index.get_level_values('State_Name').tolist(),
'district' : crop_dt[crop_dt.index.get_level_values('Crop_Year')==yr].loc[(['Tamil Nadu']), :].index.get_level_values('District_Name').tolist()
}
source.data = new_data

Loss of Bokeh charts interactivity on Mobile

I've set some charts up in Bokeh, which I'm generally very happy with on desktop screens.
However, when I open them on a mobile screen I have several functionality issues that makes them really horrible to use:
The hover functionality won't work (or at least is very buggy). When I click certain lines nothing happens and other times it recognizes that I'm clicking a completely difference part of the screen
There is a huge white space after each chart, when I embed the HTML in a site.
Code for my charts below (I embed the resulting HTML on a website).
Any advice?
Thanks!
### V3: Top Positive words
from bokeh.io import output_notebook, show, output_file, save, output
from bokeh.plotting import figure
from bokeh.models import ColumnDataSource, HoverTool, Legend
from bokeh.embed import file_html
from google.colab import files
from bokeh.io import curdoc # removes old html runs # https://github.com/bokeh/bokeh/issues/5681
curdoc().clear()
output_notebook()
use = pos_tailor
# set out axes
x = 'time_rnd'
y = 'count'
# Add annotations
# set colour palette
col_brew = ['#8dd3c7','#ffffb3','#bebada','#fb8072','#80b1d3','#fdb462','#b3de69','#fccde5','#d9d9d9','#bc80bd','#ccebc5','#ffed6f']
# map out figure
plot = figure(tools='', x_axis_type='datetime', sizing_mode='scale_both', toolbar_location='above')
# add HoverTool
hover_info = [('time', '#hover_time'),
('word', '#word'),
('count', '#count')]
hover = HoverTool(names=['use'],tooltips=hover_info,
mode='mouse',
show_arrow=True
)
plot.add_tools(hover)
# FORMAT
plot.title.text = 'Positive Deep Dive: Key Callouts'
plot.title.align = "center"
plot.axis.minor_tick_in = -3
plot.axis.minor_tick_out = 6
plot.xaxis.axis_label = 'Time'
plot.xaxis.axis_label_standoff = 15
plot.yaxis.axis_label = 'Count'
plot.yaxis.major_label_text_color = "orange"
plot.yaxis.axis_label_standoff = 15
### FOR LOOP Data
# https://stackoverflow.com/questions/46730609/position-the-legend-outside-the-plot-area-with-bokeh
legend_it = []
for i in use:
df_eng_word = df_eng_timeline[df_eng_timeline['word']==i]
source = ColumnDataSource(df_eng_word)
c = plot.line(x, y, line_width = 3,
line_alpha = 0.5, line_color=col_brew[use.tolist().index(i)],
hover_line_alpha = 1.0,
hover_line_color = 'grey',
#hover_line_color = col_brew[top_wds.index(i)],
source = source, name = 'use'
)
# materialize the plot
show(plot)
# output html file
output_file("v2_postail.html")
save(plot)
files.download('v2_postail.html')

Categories

Resources