Pie and donut charts#
Bokeh does not have built-in APIs for pie and donut charts. However, you can use Bokeh’s various wedge glyphs to create these kinds of charts.
Glyphs#
Wedge#
The wedge()
glyph method renders a filled wedge. It accepts radius
,
start_angle
, and end_angle
to determine position. Additionally, the
direction
property determines whether to render clockwise ("clock"
)
or anti-clockwise ("anticlock"
) between the start and end angles.
from bokeh.plotting import figure, show
p = figure(width=400, height=400)
p.wedge(x=[1, 2, 3], y=[1, 2, 3], radius=0.2, start_angle=0.4, end_angle=4.8,
color="firebrick", alpha=0.6, direction="clock")
show(p)
Annular wedge#
The annular_wedge()
glyph method is similar to wedge()
but leaves an inner
portion of the wedge hollow. It accepts an inner_radius
and
outer_radius
instead of just radius
.
from bokeh.plotting import figure, show
p = figure(width=400, height=400)
p.annular_wedge(x=[1, 2, 3], y=[1, 2, 3], inner_radius=0.1, outer_radius=0.25,
start_angle=0.4, end_angle=4.8, color="green", alpha=0.6)
show(p)
Annulus#
Finally, the annulus()
glyph method also accepts inner_radius
and
outer_radius
to produce hollow circles.
Pie chart#
Use the wedge glyph for each of the pie slices to create a pie chart:
from math import pi
import pandas as pd
from bokeh.palettes import Category20c
from bokeh.plotting import figure, show
from bokeh.transform import cumsum
x = {
'United States': 157,
'United Kingdom': 93,
'Japan': 89,
'China': 63,
'Germany': 44,
'India': 42,
'Italy': 40,
'Australia': 35,
'Brazil': 32,
'France': 31,
'Taiwan': 31,
'Spain': 29,
}
data = pd.Series(x).reset_index(name='value').rename(columns={'index': 'country'})
data['angle'] = data['value']/data['value'].sum() * 2*pi
data['color'] = Category20c[len(x)]
p = figure(height=350, title="Pie Chart", toolbar_location=None,
tools="hover", tooltips="@country: @value", x_range=(-0.5, 1.0))
p.wedge(x=0, y=1, radius=0.4,
start_angle=cumsum('angle', include_zero=True), end_angle=cumsum('angle'),
line_color="white", fill_color='color', legend_field='country', source=data)
p.axis.axis_label = None
p.axis.visible = False
p.grid.grid_line_color = None
show(p)
Donut chart#
Donut charts are similar to pie charts, but employ annular wedges to partition a ring region:
from math import pi
from bokeh.io import show
from bokeh.models import (AnnularWedge, ColumnDataSource,
Legend, LegendItem, Plot, Range1d)
from bokeh.sampledata.browsers import browsers_nov_2013 as df
xdr = Range1d(start=-2, end=2)
ydr = Range1d(start=-2, end=2)
plot = Plot(x_range=xdr, y_range=ydr)
plot.title.text = "Web browser market share (November 2013)"
plot.toolbar_location = None
colors = {
"Chrome": "seagreen",
"Firefox": "tomato",
"Safari": "orchid",
"Opera": "firebrick",
"IE": "skyblue",
"Other": "lightgray",
}
aggregated = df.groupby("Browser").sum(numeric_only=True)
selected = aggregated[aggregated.Share >= 1].copy()
selected.loc["Other"] = aggregated[aggregated.Share < 1].sum()
browsers = selected.index.tolist()
angles = selected.Share.map(lambda x: 2*pi*(x/100)).cumsum().tolist()
browsers_source = ColumnDataSource(dict(
start = [0] + angles[:-1],
end = angles,
colors = [colors[browser] for browser in browsers],
))
glyph = AnnularWedge(x=0, y=0, inner_radius=0.9, outer_radius=1.8,
start_angle="start", end_angle="end",
line_color="white", line_width=3, fill_color="colors")
r= plot.add_glyph(browsers_source, glyph)
legend = Legend(location="center")
for i, name in enumerate(colors):
legend.items.append(LegendItem(label=name, renderers=[r], index=i))
plot.add_layout(legend, "center")
show(plot)