Donut Chart with Bokeh

In [1]:
import pandas as pd
In [2]:
student = pd.read_csv("student.csv")
In [3]:
from math import pi

import pandas as pd

from bokeh.io import push_notebook, show, output_notebook
from bokeh.palettes import Category20c
from bokeh.layouts import row 
from bokeh.plotting import figure
from bokeh.transform import cumsum
output_notebook()
Loading BokehJS ...
In [4]:
x=student['Mjob'].value_counts()
In [5]:
data = pd.Series(x).reset_index(name='value').rename(columns={'index':'job'})
In [6]:
data
Out[6]:
job value
0 other 258
1 services 136
2 at_home 135
3 teacher 72
4 health 48
In [7]:
data['angle'] = data['value']/data['value'].sum() * 2*pi
In [8]:
data['angle']
Out[8]:
0    2.497784
1    1.316661
2    1.306980
3    0.697056
4    0.464704
Name: angle, dtype: float64
In [9]:
data['color'] = Category20c[len(x)]
In [10]:
data['color']
Out[10]:
0    #3182bd
1    #6baed6
2    #9ecae1
3    #c6dbef
4    #e6550d
Name: color, dtype: object
In [11]:
z=110*(data['value']/data['value'].sum())
In [12]:
data['value']=z
In [13]:
data
Out[13]:
job value angle color
0 other 43.728814 2.497784 #3182bd
1 services 23.050847 1.316661 #6baed6
2 at_home 22.881356 1.306980 #9ecae1
3 teacher 12.203390 0.697056 #c6dbef
4 health 8.135593 0.464704 #e6550d
In [14]:
p = figure(plot_height=350, title="", toolbar_location=None,
           tools="hover", tooltips="@job: @value{0.2f} %", x_range=(-.5, .5))

p.annular_wedge(x=0, y=1,  inner_radius=0.15, outer_radius=0.25, direction="anticlock",
                start_angle=cumsum('angle', include_zero=True), end_angle=cumsum('angle'),
        line_color="white", fill_color='color', legend='job', source=data)
Out[14]:
GlyphRenderer(
id = '2345e99c-0ac2-43ab-9a1b-781566887be7', …)
In [15]:
p.axis.axis_label=None
p.axis.visible=False
p.grid.grid_line_color = None
In [16]:
show(p)

Let's make a Donut Chart with a half circle

In [19]:
x=student['Mjob'].value_counts()
In [20]:
data = pd.Series(x).reset_index(name='value').rename(columns={'index':'job'})
In [21]:
data
Out[21]:
job value
0 other 258
1 services 136
2 at_home 135
3 teacher 72
4 health 48

We need then to divide only by $\pi$ instead of $2\pi$

In [22]:
data['angle'] = data['value']/data['value'].sum() * pi
In [23]:
data['angle'].sum()
Out[23]:
3.1415926535897927
In [24]:
z=110*(data['value']/data['value'].sum())
In [25]:
data['value']=z
In [26]:
data['color'] = Category20c[len(x)]
In [27]:
data
Out[27]:
job value angle color
0 other 43.728814 1.248892 #3182bd
1 services 23.050847 0.658331 #6baed6
2 at_home 22.881356 0.653490 #9ecae1
3 teacher 12.203390 0.348528 #c6dbef
4 health 8.135593 0.232352 #e6550d
In [28]:
p = figure(plot_height=350, title="", toolbar_location=None,
           tools="hover", tooltips="@job: @value{0.2f} %", x_range=(-.5, .5))

p.annular_wedge(x=0, y=0,  inner_radius=0.15, outer_radius=0.25, direction="anticlock",
                start_angle=cumsum('angle', include_zero=True), end_angle=cumsum('angle'),
        line_color="white", fill_color='color', legend='job', source=data)
Out[28]:
GlyphRenderer(
id = 'd38a4fef-2489-4a33-bde7-775497e4c9da', …)
In [29]:
p.axis.axis_label=None
p.axis.visible=False
p.grid.grid_line_color = None
show(p)