Bokeh Plot with Selectable Columns
Introduction
Bokeh is an interactive visualization library that allows users to create web-based interactive plots and dashboards. In this article, we will explore how to use Bokeh to create a plot where the user can select different columns from a pandas DataFrame.
We will also cover the concepts of ColumnDataSource, CustomJS, and Select in Bokeh. These are essential components for creating dynamic and interactive visualizations with Bokeh.
Setting Up the Environment
To start working with Bokeh, we need to install it using pip:
pip install bokeh pandas matplotlib numpy
We also need to have pandas, matplotlib, and numpy installed in our environment.
Creating the DataFrame
First, let’s create a sample DataFrame with several columns and a numeric index.
import pandas as pd
df = pd.DataFrame({'2007':[10,20,30,40],
'2008':[90,60,70,40],
'2009':[30,60,70,10],
'2010':[80,50,30,10]},
index=[0, 0.5, 1, 1.5])
Creating the Plot
Next, we create a figure with a linear x-axis and add a line renderer for one of the columns.
from bokeh.plotting import figure
from bokeh.models import ColumnDataSource, CustomJS
from bokeh.io import show
from bokeh.models.tools import HoverTool
from bokeh.models import Select
from bokeh.layouts import column
ds = ColumnDataSource(df)
p = figure(toolbar_location="above",
x_axis_type="linear")
p.line(source=ds, y='index', x='2007')
Creating the Select Widget
We create a Select widget with options that correspond to the columns in our DataFrame.
select = Select(title="df-column:", options=list(df.columns))
Connecting the Select Widget to the CustomJS Function
We connect the Select widget’s ‘value’ event to a CustomJS function that updates the glyph.x value of the line renderer.
handler = CustomJS(args=dict(source=ds, line_renderer=p.line), code="""
// Update glyph.x based on selected column
""")
select.js_on_change('value', handler)
Displaying the Plot
Finally, we display the plot with the Select widget.
show(column(select, p))
Understanding the Code
Let’s break down the CustomJS function:
handler = CustomJS(args=dict(source=ds, line_renderer=p.line), code="""
line_renderer.glyph.x = {field: cb_obj.value};
""")
In this function:
source
: refers to the ColumnDataSource object created earlier.line_renderer
: refers to the p.line method that creates a line renderer.cb_obj.value
: refers to the value selected by the user in the Select widget.
The CustomJS function updates the glyph.x value of the line renderer based on the selected column. This allows the user to change the x-axis values for different columns.
Troubleshooting
One potential issue with this code is that it assumes the user will always select a valid column from the DataFrame. If the user selects an invalid column, the plot may not update correctly. To fix this, we can add some error handling to ensure that only valid columns are selected:
handler = CustomJS(args=dict(source=ds, line_renderer=p.line), code="""
if (cb_obj.value in df.columns) {
line_renderer.glyph.x = {field: cb_obj.value};
} else {
console.error("Invalid column selected");
}
""")
Conclusion
In this article, we explored how to use Bokeh to create a plot where the user can select different columns from a pandas DataFrame. We covered the concepts of ColumnDataSource, CustomJS, and Select in Bokeh, and provided example code to demonstrate how to connect these components together.
By following these steps and using the custom JavaScript function, you can create dynamic and interactive visualizations with Bokeh that allow users to explore your data in new ways.
Advanced Topics
Using Multiple Lines Renderers
To add multiple lines renderers to the plot, we can use a list comprehension to create a list of line renderer objects:
line_renderers = [p.line('2007', 'index', source=ds) for column in df.columns]
We can then update each line renderer using a separate CustomJS function:
handler1 = CustomJS(args=dict(source=ds, line_renderer=line_renderers[0]), code="""
line_renderer.glyph.x = {field: cb_obj.value};
""")
handler2 = CustomJS(args=dict(source=ds, line_renderer=line_renderers[1]), code="""
line_renderer.glyph.x = {field: cb_obj.value};
""")
select.js_on_change('value', [handler1, handler2])
This allows the user to select different columns and view their corresponding lines in the plot.
Using Hover Tool
To add a hover tool to the plot, we can use the HoverTool class:
hover = HoverTool(tooltips=[("x", "@x"), ("y", "@y")])
We can then add this hover tool to the plot using the add_tools
method:
p.add_tools(hover)
This allows the user to view the x and y values of each data point when they hover over it in the plot.
Last modified on 2023-09-11