Bokeh is a Python interactive visualization library that targets modern web browsers for presentation providing elegant, concise construction of novel graphics with high-performance interactivity over very large or streaming datasets in a quick and easy way.
Offering both powerful and flexible features to enable very advanced customizations in one hand and simplicity on the other, Bokeh exposes different interface levels to the users:
This Quickstart focuses on the bokeh.plotting interface.
There are a few different ways to install Bokeh.
If you are using the Anaconda Python distribution (which is recommended), enter this command at a Bash or Windows command prompt:
conda install bokeh
This installs all the dependencies that you need to be ready to run Bokeh
and we strongly recommend using it. It reduces the installation effort to
nearly zero on any platform and configuration (including Windows). It also
installs the examples into the examples/
subdirectory of your Anaconda (or
miniconda) installation directory.
If you are confident that you have dependencies such as NumPy, Pandas, and Redis
installed, then you can also use pip
at the command line:
pip install bokeh
Note
The pip
method does not install the examples. Clone the Git repository
and look in the examples/
directory of the checkout to see examples.
Windows users, see Notes for Windows Users in the Installation section.
Bokeh is a large library that exposes many capabilities, so this section is only a quick tour of some common Bokeh use-cases and workflows. For more detailed information please consult the full User Guide.
Let’s begin with some examples.
Plotting some data in basic Python lists as a line chart including zoom, pan, resize, save, and other tools is simple and straightforward:
from bokeh.plotting import figure, output_file, show
# prepare some data
x = [1, 2, 3, 4, 5]
y = [6, 7, 2, 4, 5]
# output to static HTML file
output_file("lines.html", title="line plot example")
# create a new plot with a title and axis labels
p = figure(title="simple line example", x_axis_label='x', y_axis_label='y')
# add a line renderer with legend and line thickness
p.line(x, y, legend="Temp.", line_width=2)
# show the results
show(p)
When you execute this script, you will see that a new output file
"lines.html"
is created, and that a browser automaticaly opens a new tab
to display it. (For presentation purposes we have included the plot output
directly inline in this document.)
The basic steps to creating plots with the bokeh.plotting interface are:
output_file()
,
with "lines.html"
as the filename to save as).figure()
to create a plot with some overall options like title,
tools and axes labels.Figure.line
) for our data, with visual
customizations like colors, legends and widths to the plot.show()
or save()
the results.Steps three and four can be repeated to create more than one plot. See some examples of this below.
The bokeh.plotting interface is also quite handy if we need to customize the output a bit more by adding more data series, glyphs, logarithmic axis, etc. It’s also possible to easily combine multiple glyphs together on one plot as shown below:
from bokeh.plotting import figure, output_file, show
# prepare some data
x = [0.1, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0]
y0 = [i**2 for i in x]
y1 = [10**i for i in x]
y2 = [10**(i**2) for i in x]
# output to static HTML file
output_file("log_lines.html")
# create a new plot
p = figure(
tools="pan,box_zoom,reset,save",
y_axis_type="log", y_range=[0.001, 10**11], title="log axis example",
x_axis_label='sections', y_axis_label='particles'
)
# add some renderers
p.line(x, x, legend="y=x")
p.circle(x, x, legend="y=x", fill_color="white", size=8)
p.line(x, y0, legend="y=x^2", line_width=3)
p.line(x, y1, legend="y=10^x", line_color="red")
p.circle(x, y1, legend="y=10^x", fill_color="red", line_color="red", size=6)
p.line(x, y2, legend="y=10^x^2", line_color="orange", line_dash="4 4")
# show the results
show(p)
At this point we should mention Jupyter (formerly IPython) notebooks.
Jupyter notebooks are a fantastic tool for exploratory data analysis, and they
are widely used across the “PyData” community. Bokeh integrates seamlessly with
Jupyter notebooks. To view the above examples in a notebook, you would only change
output_file()
to a call to output_notebook()
instead.
A large number of static examples may be viewed directly online at the Bokeh NBViewer Gallery.
The Bokeh GitHub repository also has a number of example notebooks in the
examples/plotting/notebook/
directory. After cloning the repository,
navigate there and run:
ipython notebook
You can open and interact with any of the notebooks listed in the index page that automatically opens up. In particular, you might check out the interact_basic and interact_numba examples that show how Bokeh can be used together with Jupyter interactive widgets.
Bokeh’s architecture makes it easy to create bindings for Bokeh in other languages, and in fact several already exist. We are obviously big Python fans, but having many language options is a compelling feature. Here are some of the other ways to use Bokeh:
Some of the examples included in the Bokeh source make use of sample data files that are distributed separately. To download this data, execute the following commands at a Bash or Windows command prompt:
python -c "import bokeh.sampledata; bokeh.sampledata.download()"
Let’s consider the plots above, and use them to help define some core concepts.
Plots are a central concept in Bokeh. They are containers that hold all the
various objects (renderers, guides, data, and tools) that comprise the final
visualization that is presented to users. The bokeh.plotting interface
provides a Figure
class to help with assembling all the necessary objects,
and a convenience function figure()
for creating Figure
objects.
Glyphs are the basic visual marks that Bokeh can display. At the lowest level,
there are glyph objects, such as Line
. If you are using the low-level
bokeh.models interface, it is your responsibility to create and coordinate
all the various Bokeh objects, including glyph objects and their data sources.
To make life easier, the bokeh.plotting interface exposes higher level
glyph methods such as the Figure.line
method used in the first example.
The second example also adds in calls to Figure.circle
to display circle
and line glyphs together on the same plot. Besides lines and circles, Bokeh
makes many additional ref:glyphs <bokeh.models.glyphs> and ref:markers <bokeh.models.markers> available.
The visual appearance of a glyph is tied directly to the data values that are associated with the glyph’s various attributes. In the example above we see that positional attributes like x and y can be set to vectors of data. But glyphs also have some combination of Line Properties, Fill Properties, and Text Properties to control their appearance. All of these attributes can be set with “vectorized” values as well. We will show examples of this below.
Bokeh plots can also have other visual components that aid presentation or help the user make comparisons. These fall into two categories. Guides are visual aids that help users judge distances, angles, etc. These include grid lines or bands, axes (such as linear, log, or datetime) that may have ticks and tick labels as well. Annotations are visual aids that label or name parts of the plot. These include titles, legends, etc.
Ranges describe the data-space bounds of a plot. By default, plots generated
with the bokeh.plotting interface come configured with
DataRange1d
objects that try to
automatically set the plot bounds to encompass all the available data.
But it is possible to supply explicit
Range1d
objects for fixed bounds.
As a convenience these can also typically be spelled as 2-tuples or lists:
p = figure(x_range=[0,10], y_range=(10, 20))
To generate plots, the client library BokehJS JavaScript and CSS code must
be loaded into the browser. By default, the output_file()
function will
configure Bokeh to generate static HTML files with BokehJS resources embedded
directly inside. All the examples so far do this. However, you can also
generate output that loads BokehJS from CDN, by passing the argument
mode="cdn"
to the output_file()
function.
Here are a few more examples to demonstrate other common tasks and use-cases with the bokeh.plotting interface.
This example shows how it is possible to provide sequences of data values for
glyph attributes like fill_color
and radius
. Other things to look out
for in this example:
figure()
mode
argumentx_range
and y_range
explicitlyNone
)import numpy as np
from bokeh.plotting import figure, output_file, show
# prepare some data
N = 4000
x = np.random.random(size=N) * 100
y = np.random.random(size=N) * 100
radii = np.random.random(size=N) * 1.5
colors = ["#%02x%02x%02x" % (r, g, 150) for r, g in zip(np.floor(50+2*x), np.floor(30+2*y))]
# output to static HTML file (with CDN resources)
output_file("color_scatter.html", title="color_scatter.py example", mode="cdn")
TOOLS="resize,crosshair,pan,wheel_zoom,box_zoom,reset,box_select,lasso_select"
# create a new plot with the tools above, and explicit ranges
p = figure(tools=TOOLS, x_range=(0,100), y_range=(0,100))
# add a circle renderer with vecorized colors and sizes
p.circle(x,y, radius=radii, fill_color=colors, fill_alpha=0.6, line_color=None)
# show the results
show(p)
Linking together various aspects of different plots can be a useful technique for data visualization. In Bokeh, such linkages are typically accomplished by sharing some plot component between plots. Below is an example that demonstrates linked panning (where changing the range of one plot causes others to update) by sharing range objects between the plots. Some other things to look out for in this example:
figure()
multiple times to create multiple plotsgridplot()
to arrange several plots in an arrayFigure.triangle
and
Figure.square
toolbar_location
to None
color
(sets both line_color
and
fill_color
) and alpha
(sets both line_alpha
and
fill_alpha
)import numpy as np
from bokeh.plotting import *
# prepare some data
N = 100
x = np.linspace(0, 4*np.pi, N)
y0 = np.sin(x)
y1 = np.cos(x)
y2 = np.sin(x) + np.cos(x)
# create a new plot
s1 = figure(width=250, plot_height=250, title=None)
s1.circle(x, y0, size=10, color="navy", alpha=0.5)
# NEW: create a new plot and share both ranges
s2 = figure(width=250, height=250, x_range=s1.x_range, y_range=s1.y_range, title=None)
s2.triangle(x, y1, size=10, color="firebrick", alpha=0.5)
# NEW: create a new plot and share only one range
s3 = figure(width=250, height=250, x_range=s1.x_range, title=None)
s3.square(x, y2, size=10, color="olive", alpha=0.5)
# NEW: put the subplots in a gridplot
p = gridplot([[s1, s2, s3]], toolbar_location=None)
# show the results
show(p)
Although the toolbar is hidden, the pan tool is still present and active. Click and drag the above plots to pan them, and see how their ranges are linked together.
Another linkage that is often useful is linked brushing (where a selection
on one plot causes a selection to update on other plots). Below is an example
that demonstrates linked brushing by sharing a ColumnDataSource
between two
plots:
import numpy as np
from bokeh.plotting import *
from bokeh.models import ColumnDataSource
# prepare some date
N = 300
x = np.linspace(0, 4*np.pi, N)
y0 = np.sin(x)
y1 = np.cos(x)
# output to static HTML file
output_file("linked_brushing.html")
# NEW: create a column data source for the plots to share
source = ColumnDataSource(data=dict(x=x, y0=y0, y1=y1))
TOOLS = "pan,wheel_zoom,box_zoom,reset,save,box_select,lasso_select"
# create a new plot and add a renderer
left = figure(tools=TOOLS, width=350, height=350, title=None)
left.circle('x', 'y0', source=source)
# create another new plot and add a renderer
right = figure(tools=TOOLS, width=350, height=350, title=None)
right.circle('x', 'y1', source=source)
# put the subplots in a gridplot
p = gridplot([[left, right]])
# show the results
show(p)
Choose the box or lasso select tool, and click and drag to make a selection on one plot, which will update the selection on the other plot.
Dealing with date and time series is another common task. Bokeh has a
sophisticated DatetimeAxis
that can change the displayed ticks based
on the current scale of the plot. There are some inputs for which Bokeh
will automatically default to DatetimeAxis
, but you can always
explicitly ask for one by passing the value "datetime"
to the
x_axis_type
or y_axis_type
parameters to figure()
. A few things
of interest to look out for in this example:
width
and height
arguments to figure()
Figure
attributes:
legend
, grid
, xgrid
, ygrid
, axis
, xaxis
, yaxis
import numpy as np
from bokeh.plotting import figure, output_file, show
from bokeh.sampledata.stocks import AAPL
# prepare some data
aapl = np.array(AAPL['adj_close'])
aapl_dates = np.array(AAPL['date'], dtype=np.datetime64)
window_size = 30
window = np.ones(window_size)/float(window_size)
aapl_avg = np.convolve(aapl, window, 'same')
# output to static HTML file
output_file("stocks.html", title="stocks.py example")
# create a new plot with a a datetime axis type
p = figure(width=800, height=350, x_axis_type="datetime")
# add renderers
p.circle(aapl_dates, aapl, size=4, color='darkgrey', alpha=0.2, legend='close')
p.line(aapl_dates, aapl_avg, color='navy', legend='avg')
# NEW: customize by setting attributes
p.title = "AAPL One-Month Average"
p.legend.orientation = "top_left"
p.grid.grid_line_alpha=0
p.xaxis.axis_label = 'Date'
p.yaxis.axis_label = 'Price'
p.ygrid.band_fill_color="olive"
p.ygrid.band_fill_alpha = 0.1
# show the results
show(p)
Bokeh also comes with an optional server component, the bokeh-server
. It
possible to create many interesting and interactive visualizations without
using the Bokeh server, as we have seen above. However, the Bokeh server
affords many novel and powerful capabilities, including:
Details of Bokeh server usage require more space than a Quickstart allows, but you can see (and interact with) a simple Bokeh server app below:
More examples of hosted Bokeh applications can be found in the Server Examples section of the Gallery. For information about how to use the server and write Bokeh server plots and apps, consult the Deploying the Bokeh Server section of the User Guide.
This Quickstart barely scratches the surface of Bokeh capability.
For more information about the different plotting APIs Bokeh offers, using the Bokeh server, and how to embed Bokeh plots in your own apps and documents, check out the User Guide. For detailed information about all modules, classes, models, and objects, consult the Reference Guide. If you are interested in learning how to build and develop Bokeh, or for information about how to create a new language binding, see the Developer Guide.
To see ready-made examples of how you might use Bokeh with your own data, check out the Gallery. To see detailed examples and walkthroughs as well as find exercises for learning Bokeh by doing, work through the Tutorials.
For questions and technical assistance, come join the Bokeh mailing list.
Visit the Bokeh GitHub repository and try the examples.
Be sure to follow us on Twitter @bokehplots, as well as on Vine, and Youtube!