Ranges and axes#
Setting ranges#
By default, Bokeh attempts to automatically set the data bounds of plots to fit
snugly around the data. You may, however, need to set a plot’s range
explicitly. To do so, set the x_range
and/or y_range
properties using a
Range1d
object that lets you set the start and end points of the range
you want.
p.x_range = Range1d(0, 100)
For convenience, the figure()
function can also accept (start, end) tuples as
values for the x_range
or y_range
parameters. Here’s how you can use
both methods to set a range:
from bokeh.models import Range1d
from bokeh.plotting import figure, show
# create a new plot with a range set with a tuple
p = figure(width=400, height=400, x_range=(0, 20))
# set a range using a Range1d
p.y_range = Range1d(0, 15)
p.scatter([1, 2, 3, 4, 5], [2, 5, 8, 2, 7], size=10)
show(p)
Ranges also have a bounds
property that lets you specify the limits of the
plot beyond which the user cannot pan or zoom.
# set a range using a Range1d
p.y_range = Range1d(0, 15, bounds=(0, None))
Axis types#
All the examples above use the default linear axis. This axis is suitable for plots that need to show numerical data on a linear scale. However, you may have categorical data or need to display numerical data on a datetime or log scale. This section shows you how to specify the axis type when using the bokeh.plotting interface.
Categorical axes#
To create a categorical axis, specify a
FactorRange
for one of the plot’s ranges or a
list of factors to be converted to one. Here’s an example:
from bokeh.plotting import figure, show
factors = ["a", "b", "c", "d", "e", "f", "g", "h"]
x = [50, 40, 65, 10, 25, 37, 80, 60]
p = figure(y_range=factors)
p.scatter(x, factors, size=15, fill_color="orange", line_color="green", line_width=3)
show(p)
Datetime axes#
Note
The example in this section requires a network connection and depends on the open source Pandas library to present realistic time series data.
For time series, or any data that involves dates or time, you may want to use axes with labels suitable for different date and time scales.
The figure()
function accepts x_axis_type
and y_axis_type
as arguments.
To specify a datetime axis, pass "datetime"
for the value of either of
these parameters.
import pandas as pd
from bokeh.plotting import figure, show
from bokeh.sampledata.stocks import AAPL
df = pd.DataFrame(AAPL)
df['date'] = pd.to_datetime(df['date'])
# create a new plot with a datetime axis type
p = figure(width=800, height=250, x_axis_type="datetime")
p.line(df['date'], df['close'], color='navy', alpha=0.5)
show(p)
Note
Future versions of Bokeh will attempt to auto-detect situations when datetime axes are appropriate and add them automatically.
Log scale axes#
Data that grows exponentially or covers many orders of magnitude often requires one axis to be on a log scale. For data that has a power law relationship, you may want to use log scales on both axes.
You can use the same figure()
arguments, x_axis_type
and y_axis_type
,
to set one or both of the axes to "log"
.
By default, Bokeh calculates log axis ranges to fit around positive value data. For information on how to set your own ranges, see Setting ranges.
from bokeh.plotting import figure, show
x = [0.1, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0]
y = [10**xx for xx in x]
# create a new plot with a log axis type
p = figure(width=400, height=400, y_axis_type="log")
p.line(x, y, line_width=2)
p.scatter(x, y, fill_color="white", size=8)
show(p)
Mercator axes#
Mercator axes are useful for tile sources. You can use the same figure()
arguments, x_axis_type
and y_axis_type
,
to set one or both of the axes to "mercator"
.
from bokeh.plotting import figure, show
# range bounds supplied in web mercator coordinates
p = figure(x_range=(-2000000, 2000000), y_range=(1000000, 7000000),
x_axis_type="mercator", y_axis_type="mercator")
p.add_tile("CartoDB Positron", retina=True)
show(p)
Twin axes#
You can add multiple axes representing different ranges to a single plot. To do
this, configure the plot with “extra” named ranges in the extra_x_range
and
extra_y_range
properties. You can then refer to these named ranges when
adding new glyph methods as well as when adding new axis objects with the
add_layout
method of the Plot
. Here’s an example:
from numpy import arange, linspace, pi, sin
from bokeh.layouts import column
from bokeh.models import (CustomJS, LinearAxis, Range1d, Select,
WheelZoomTool, ZoomInTool, ZoomOutTool)
from bokeh.palettes import Sunset6
from bokeh.plotting import figure, show
x = arange(-2*pi, 2*pi, 0.2)
y = sin(x)
y2 = linspace(0, 100, len(x))
blue, red = Sunset6[2], Sunset6[5]
p = figure(x_range=(-2*pi, 2*pi), y_range=(-1, 1), tools="pan,box_zoom,save,reset")
p.background_fill_color = "#fafafa"
blue_circles = p.scatter(x, y, line_color="black", fill_color=blue, size=12)
p.axis.axis_label = "light blue circles"
p.axis.axis_label_text_color = blue
p.extra_x_ranges['foo'] = Range1d(-2*pi, 2*pi)
p.extra_y_ranges['foo'] = Range1d(0, 100)
red_circles = p.scatter(x, y2, color=red, size=8,
x_range_name="foo",
y_range_name="foo",
)
ax2 = LinearAxis(
axis_label="red circles",
x_range_name="foo",
y_range_name="foo",
)
ax2.axis_label_text_color = red
p.add_layout(ax2, 'left')
ax3 = LinearAxis(
axis_label="red circles",
x_range_name="foo",
y_range_name="foo",
)
ax3.axis_label_text_color = red
p.add_layout(ax3, 'below')
wheel_zoom = WheelZoomTool()
p.add_tools(wheel_zoom)
p.toolbar.active_scroll = wheel_zoom
zoom_in_blue = ZoomInTool(renderers=[blue_circles], description="Zoom in blue circles")
zoom_out_blue = ZoomOutTool(renderers=[blue_circles], description="Zoom out blue circles")
p.add_tools(zoom_in_blue, zoom_out_blue)
zoom_in_red = ZoomInTool(renderers=[red_circles], description="Zoom in red circles")
zoom_out_red = ZoomOutTool(renderers=[red_circles], description="Zoom out red circles")
p.add_tools(zoom_in_red, zoom_out_red)
select = Select(title="Zoom together:", options=["none", "cross", "all"], value=wheel_zoom.zoom_together)
select.js_on_change("value", CustomJS(
args=dict(select=select, wheel_zoom=wheel_zoom),
code="""\
export default ({select, wheel_zoom}) => {
wheel_zoom.zoom_together = select.value
}
""",
))
show(column(select, p))
Fixed location axis#
By default Bokeh places axes on the sides of plots, but it is possible to
locate axes anywhere along a range by setting their fixed_location
property:
import numpy as np
from bokeh.plotting import figure, show
x = np.linspace(-6, 6, 500)
y = 8*np.sin(x)*np.sinc(x)
p = figure(width=800, height=300, title="", tools="",
toolbar_location=None, match_aspect=True)
p.line(x, y, color="navy", alpha=0.4, line_width=4)
p.background_fill_color = "#efefef"
p.xaxis.fixed_location = 0
p.yaxis.fixed_location = 0
show(p)