bokeh 5th: project interactive data visualization web app
How to make useful and fun interactive data visualization web apps and how to deploy them online for public access?
Click App runs on Here, will be interactive and animated.
Click App runs on Here, will be interactive and animated.
gapminder project¶
In [1]:
from bokeh.sampledata.gapminder import life_expectancy, population, fertility, regions
import pandas as pd
from bokeh.io import output_file, output_notebook, show, curdoc
from bokeh.plotting import figure
from bokeh.models import HoverTool, ColumnDataSource
from bokeh.charts import Scatter
In [2]:
output_notebook()
In [3]:
life_expectancy.shape, population.shape, fertility.shape, regions.shape
Out[3]:
In [4]:
life_expectancy.head(1)
Out[4]:
In [5]:
population.head(1)
Out[5]:
In [6]:
fertility.head(1)
Out[6]:
In [7]:
regions.head(1)
Out[7]:
In [8]:
life2000=life_expectancy['2000'].to_frame()
fert2000=fertility['2000'].to_frame()
pop2000=population['2000'].to_frame()
In [9]:
two=pd.merge(life2000,fert2000,left_index=True,right_index=True)
In [10]:
three=pd.merge(two, pop2000,left_index=True,right_index=True )
In [11]:
# pd.concat([life2000,fert2000],axis=1)
three['country']=three.index
In [12]:
three.columns=['life2000','fertility2000','population2000','country']
In [13]:
three.head(1)
Out[13]:
In [14]:
p = figure(title='2000', x_axis_label='Fertility (children per woman)', y_axis_label='Life Expectancy (years)',
plot_height=400, plot_width=700,
# tools=[HoverTool(tooltips=[('where','@country')])],
tools=[HoverTool(tooltips='@country')],
)
data_source = ColumnDataSource(data={
'x' : three.fertility2000,
'y' : three.life2000,
'country' :three['country'],
})
p.circle(x='x', y='y', source=data_source, size=12, alpha=.4, color='red')
curdoc().add_root(p)
curdoc().title = 'Gapminder'
show(p)
- add hover tool to Scatter charts
- over tool can be added to line charts as well
In [15]:
# p=Scatter(two, x='life2000',y='fertility2000',
# title='life vs fertility in 2000',
# plot_width=400,plot_height=200,
# tooltips=[('where','@country')])
# show(p)
interactive deploy on server¶
- add Slider
- deploy on server
In [16]:
from bokeh.sampledata.gapminder import life_expectancy, population, fertility, regions
from bokeh.io import output_file, output_notebook, show, curdoc
from bokeh.plotting import figure
from bokeh.models import HoverTool, ColumnDataSource
In [17]:
from bokeh.layouts import widgetbox, row, column
from bokeh.models import Slider
from bokeh.models import LinearColorMapper
In [18]:
data_column=ColumnDataSource(data={
'fertility' : fertility['1970'],
'life' : life_expectancy['1970'],
'country' : population.index,
'pop' : (population['1970']/ 20000000) + 2,
})
In [19]:
def update_plot(attr, old, new):
yr = slider.value
yr=str(yr)
new_data = {
'fertility' : fertility[yr],
'life' : life_expectancy[yr],
'country' : population.index,
'pop' : (population[yr]/ 20000000) + 2,
}
data_column.data = new_data
p.title.text = "Gapminder data for %s"% yr
In [20]:
slider = Slider(start=1964,end=2013,step=1,value=1970,title='Year')
slider.on_change('value',update_plot)
try add diff colors¶
In [21]:
mapper=LinearColorMapper(['silver','orange','purple','red'])
In [ ]:
In [22]:
TOOLS="crosshair,pan,wheel_zoom,box_zoom,undo,redo,reset,tap,save,box_select,poly_select,lasso_select,"
p = figure(title='Gapminder', x_axis_label='Fertility (children per woman)', y_axis_label='Life Expectancy (years)',
plot_height=600, plot_width=950,
# tools=[HoverTool(tooltips=[('where','@country')])],
tools=[HoverTool(tooltips='@country',mode='vline'),TOOLS])
p.circle(x='fertility', y='life', source=data_column, size=15,
alpha=.4, hover_color='green',
color={'field':'fertility','transform':mapper})
Out[22]:
In [23]:
layout = column(widgetbox(slider), p)
curdoc().add_root(layout)
curdoc().title = 'Gapminder_server'
show(layout)
In [24]:
from bokeh.sampledata.gapminder import life_expectancy, population, fertility, regions
from bokeh.io import output_file, output_notebook, show, curdoc
from bokeh.plotting import figure
from bokeh.models import HoverTool, ColumnDataSource
from bokeh.layouts import widgetbox, row, column
from bokeh.models import Slider
from bokeh.models import LinearColorMapper
from bokeh.models import Select, Button, Label
from bokeh.models.widgets import Div
# population=population/100000000
from numpy import log10
population=log10(population)
create={'fertility':fertility, 'life':life_expectancy, 'population':population}
mapper=LinearColorMapper(['silver','orange','purple','red'])
TOOLS="crosshair,pan,wheel_zoom,box_zoom,undo,redo,reset,tap,save,box_select,poly_select,lasso_select,"
data_column=ColumnDataSource(data={
'x' : create['fertility']['1970'],
'y' : create['life']['1970'],
'country' : population.index,
'pop':population['1970']*3
})
In [25]:
def update_plot(attr, old, new):
yr = slider.value
yr=str(yr)
x = x_select.value
y = y_select.value
new_data = {
'x' : create[x][yr],
'y' : create[y][yr],
'country' : population.index,
'pop':population[yr]*3
}
data_column.data = new_data
p.title.text = "Gapminder data for %s"% yr
p.xaxis.axis_label=x
p.yaxis.axis_label=y
# Set the range of all axes
p.x_range.start = min(create[x][yr])
p.x_range.end = max(create[x][yr])
p.y_range.start = min(create[y][yr])
p.y_range.end = max(create[y][yr])
p = figure(title='Gapminder', x_axis_label='Fertility (children per woman)', y_axis_label='Life Expectancy (years)',
plot_height=600, plot_width=950,
# tools=[HoverTool(tooltips=[('where','@country')])],
tools=[HoverTool(tooltips='@country',mode='vline'),TOOLS])
p.circle(x='x', y='y', source=data_column, size='pop',
alpha=.4, hover_color='green',
color={'field':'x','transform':mapper})
Out[25]:
In [26]:
div = Div(text="""<br><hr><span style="font-size: 12pt;">This is a Data Visualization web app test I created using <span style="background-color: #deffde;">Bokeh</span> and deployed in my <span style="background-color: #deffde;">AWS</span>.</span>
<br>
<p style="text-align: right;"><span style="font-size: 16pt;">Go <span style="background-color: #deeeff;">back</span> to <span style="color: #ae5eff;"><a style="color: #ae5eff;" href="http://shichaoji.com">my blog</a></span></span>
<span style="font-size: 12pt;"><br><br><em><span style="color: #007fff;">Shichao Ji</span></em></span></p>""",
width=200, height=100)
In [27]:
x_select = Select(
options=['fertility', 'life', 'population'],
value='fertility',
title='x-axis data'
)
y_select = Select(
options=['fertility', 'life', 'population'],
value='life',
title='y-axis data'
)
# Attach the update_plot callback to the 'value' property of x_select
x_select.on_change('value', update_plot)
y_select.on_change('value', update_plot)
slider = Slider(start=1964,end=2013,step=1,value=1970,title='Year')
slider.on_change('value',update_plot)
def animate_update():
year = slider.value + 1
if year > 2013:
year = 1964
slider.value = year
def animate():
if button.label == 'Play':
button.label = 'Pause'
curdoc().add_periodic_callback(animate_update, 200)
else:
button.label = 'Play'
curdoc().remove_periodic_callback(animate_update)
button = Button(label='Play', width=120)
button.on_click(animate)
layout = row(widgetbox(slider, x_select, y_select,button, div), p)
curdoc().add_root(layout)
curdoc().title = 'Gapminder_server'
show(layout)
In [28]:
output_notebook()
In [29]:
curdoc().add_periodic_callback
Out[29]:
In [ ]:
the source code that I deployed on AWS¶
In [30]:
from bokeh.sampledata.gapminder import life_expectancy, population, fertility, regions
from bokeh.io import output_file, output_notebook, show, curdoc
from bokeh.plotting import figure
from bokeh.models import HoverTool, ColumnDataSource
from bokeh.layouts import widgetbox, row, column
from bokeh.models import Slider
from bokeh.models import LinearColorMapper
from bokeh.models import Select, Button, Label
from bokeh.models.widgets import Div
##population=population/20000000 +2
from numpy import log10, exp
pop=log10(population)
population=population/1000000
create={'fertility':fertility, 'life':life_expectancy, 'log10(population)':pop}
mapper=LinearColorMapper(['green','orange','purple','red'])
TOOLS="crosshair,pan,wheel_zoom,box_zoom,undo,redo,reset,tap,save,box_select,poly_select,lasso_select,"
data_column=ColumnDataSource(data={
'x' : create['fertility']['1970'],
'y' : create['life']['1970'],
'country' : population.index,
'pop': exp(pop['1970'])/100*1.3,
'population':population['1970'],
})
def update_plot(attr, old, new):
yr = slider.value
yr=str(yr)
x = x_select.value
y = y_select.value
new_data = {
'x' : create[x][yr],
'y' : create[y][yr],
'country' : population.index,
'pop': exp(pop[yr])/100*1.3,
'population':population[yr],
}
data_column.data = new_data
p.title.text = "Gapminder data for %s"% yr
p.xaxis.axis_label=x
p.yaxis.axis_label=y
# Set the range of all axes
p.x_range.start = min(create[x][yr])
p.x_range.end = max(create[x][yr])
p.y_range.start = min(create[y][yr])
p.y_range.end = max(create[y][yr])
tips=[('Country','@country'),('X value','@x'),('Y value','@y'),('Population','@population million')]
p = figure(title='Gapminder', x_axis_label='Fertility (children per woman)', y_axis_label='Life Expectancy (years)',
plot_height=600, plot_width=950,
tools=[HoverTool(tooltips=tips),TOOLS],
)
p.circle(x='x', y='y', source=data_column, size='pop',
alpha=.4, hover_color='cyan',
color={'field':'x','transform':mapper})
div = Div(text="""<br><br><hr><span style="font-size: 12pt;">This is a Data Visualization web app test I created using <span style="background-color: #deffde;">Bokeh</span> and deployed in my <span style="background-color: #deffde;">AWS</span>.</span>
<br>
<p style="text-align: right;"><span style="font-size: 16pt;">Go <span style="background-color: #deeeff;">back</span> to <span style="color: #ae5eff;"><a style="color: #ae5eff;" href="http://shichaoji.com">my blog</a></span></span>
<span style="font-size: 12pt;"><br><br><em><span style="color: #007fff;">Shichao Ji</span></em></span></p>""",
width=200, height=100)
x_select = Select(
options=['fertility', 'life', 'log10(population)'],
value='fertility',
title='x-axis data'
)
y_select = Select(
options=['fertility', 'life', 'log10(population)'],
value='life',
title='y-axis data'
)
# Attach the update_plot callback to the 'value' property of x_select
x_select.on_change('value', update_plot)
y_select.on_change('value', update_plot)
slider = Slider(start=1964,end=2013,step=1,value=1970,title='Year')
slider.on_change('value',update_plot)
def animate_update():
year = slider.value + 1
if year > 2013:
year = 1964
slider.value = year
def animate():
if button.label == 'Play':
button.label = 'Pause'
curdoc().add_periodic_callback(animate_update, 200)
else:
button.label = 'Play'
curdoc().remove_periodic_callback(animate_update)
button = Button(label='Play', width=120)
button.on_click(animate)
layout = row(widgetbox(slider, x_select, y_select, button, div), p)
# curdoc().add_root(layout)
curdoc().title = 'Gapminder_server'
show(layout)
In [ ]: