Reputation: 1061
I am very new to Bokeh and cannot seem to find any really good examples of a simple dropdown plot with data from a pandas dataframe. I am working with a dictionary that has 4 different keys, where each key contains a dataframe.
df_vals.keys()
dict_keys(['corn', 'soybeans', 'winterwheat', 'springwheat'])
df_vals['corn'].head()
time 2m_temp_prod 2m_temp_area total_precip_prod total_precip_area
0 2020-09-16 00:00:00 299.346777 299.799234 0.000000 0.000000
1 2020-09-16 06:00:00 294.039512 294.443352 0.191070 0.286952
2 2020-09-16 12:00:00 292.959274 293.182931 0.155765 0.216606
3 2020-09-16 18:00:00 301.318046 301.767516 0.421768 0.485691
4 2020-09-17 00:00:00 300.623567 300.979650 0.363572 0.501164
Next, I can add this data to a source.
source=ColumnDataSource(data=df_vals['corn'])
Plotting from here is simple.
p1=figure(x_axis_type='datetime')
p1.line(x='time', y='2m_temp_prod',source=source)
show(p1)
This does exactly what I want. It plots a line plot with datetime as the x-axis. However, now I want to add a dropdown widget to switch between 2 columns in df_vals['corn']
(2m_temp_prod and total_precip_prod). I have tried this code below but it is not working and I am not sure if that's even the right way to go about it.
def update_plot(attr, old, new):
if new == 'total_precip_prod':
source.data = {
'x' : df_vals['corn']['time'],
'y' : df_vals['corn']['total_precip_prod'].cumsum()
}
select = Select(title="hi", options=['2m_temp_area', 'total_precip_prod'], value='2m_temp_area')
select.on_change('value', update_plot)
# Create layout and add to current document
layout = row(select, p1)
curdoc().add_root(layout)
Ideally, the button would have two options: temps and precip. How would I go about do this?
Upvotes: 0
Views: 2961
Reputation: 1446
You can use Bokeh CustomJS
callbacks to toggle visibility of the plots according to what's selected in a dropdown. A basic example would look like this:
from bokeh.models import ColumnDataSource, CustomJS, Range1d, Select
from bokeh.plotting import figure, output_notebook, show
from bokeh.layouts import column
import pandas as pd
import numpy as np
# you can also output to an HTML file
output_notebook()
# toy dataframe with two y columns you can switch between
df = pd.DataFrame(data={
"x" : range(0,100),
"y1" : np.random.randint(10, 20, 100),
"y2" : np.random.randint(40, 50, 100)
})
# fix the y_range to be the same for two lines
p = figure(y_range=Range1d(0, 60), plot_width=600, plot_height=400)
# shared datasource
source = ColumnDataSource(df)
plot_1 = p.line(x="x", y="y1", color="teal", source=source, line_width=1)
plot_2 = p.line(x="x", y="y2", color="firebrick", source=source, line_width=1)
# initialise the plot with only y1 visible - to match the dropdown default
plot_2.visible = False
# dropdown widget + Javascript code for interactivity
select = Select(title="Plot to show:", value="Line 1", options=["Line 1", "Line 2"])
select.js_on_change("value", CustomJS(args=dict(line_1=plot_1, line_2=plot_2), code="""
line_1.visible = true
line_2.visible = true
if (this.value === "Line 1") {
line_2.visible = false
} else {
line_1.visible = false
}
"""))
layout = column(select, p)
show(layout)
Upvotes: 2