<jupyter_start><jupyter_text>L03.2 Interactive plots with BokehIn order for this lecture to be standalone, we will use the dataset by the [Gapminder foundation](https://www.gapminder.org/). This dataset is very rich and allows us to demonstrate a rich demonstration of Bokeh's capabilities. Basic plot<jupyter_code>from bokeh.plotting import figure
from bokeh.io import output_file, show
import numpy as np

output_file("basic_bokeh.html")

x = np.linspace(-np.pi, np.pi, 256)
y = np.cos(x)

p = figure()
p.line(x, y)

show(p)<jupyter_output><empty_output><jupyter_text>Running this code creates a html file and opens it in your browser.<jupyter_code>output_file("basic_bokeh_pretty.html")

golden = 1.618
dpi = 75
h = int(2.5*dpi); w = int(h*golden) 

p = figure(plot_width=w, plot_height=h)
p.line(x, y, line_width=2)

p.xaxis.axis_label = "x"
p.yaxis.axis_label = "cos(x)"

p.xgrid.grid_line_color = None
p.ygrid.grid_line_color = None
p.xaxis.minor_tick_line_color = None
p.yaxis.minor_tick_line_color = None

show(p)<jupyter_output><empty_output><jupyter_text>Interactive dataset plots<jupyter_code>import pandas as pd
df = pd.read_csv("gapminder.csv")
df.info()
df['country'].unique() # Display unique entries in row 'country'
df.head(10) # display first 10 entries<jupyter_output><empty_output><jupyter_text>Looking at the head of the dataframe tells us that we have information on life expectancies, population, and GDP for each country every 5 years. This should allow us to produce some interesting plots! Bokeh Line chartsWe already used line charts in the basic plotting example. Let's check out how life expectancy has been doing over the years in Europe.<jupyter_code>is_europe = df['continent'] == "Europe"
europe = df[is_europe]
europe.head()
from bokeh.plotting import figure
from bokeh.io import show, reset_output, output_notebook
from bokeh.models import Legend, LegendItem

reset_output()
output_notebook()

# Bokeh does not automatically cycle through colours
from bokeh.palettes import Category20_20 as palette
import itertools
colors = itertools.cycle(palette) 

output_notebook()

countries = europe['country'].unique()

# Create a blank figure with labels
fig = figure(plot_width = 600, plot_height = 800, 
           title = 'Gapminder data',
           x_axis_label = 'year', y_axis_label = 'life_expectancy')

# Creating traces by looping over countries
legend_items = []
for country in countries:
    is_country = europe['country'] == country
    r = fig.line(europe[is_country]['year'],
             europe[is_country]['lifeExp'],
             line_width=2,
             color=next(colors),
             alpha=1.0,
             muted_alpha=0.0)
    legend_items.append((country, [r]))

legend = Legend(items=legend_items, location=(20, 20))
legend.click_policy = "mute"
fig.add_layout(legend, "right")
    
show(fig)
colors = itertools.cycle(palette) 

scandinavians = ['Norway', 'Sweden', 'Denmark']
is_scandinavia = europe['country'].isin(scandinavians)
scandinavia = europe[is_scandinavia]
 
fig = figure(plot_width = 600, plot_height = 600, 
           title = 'Gapminder data',
           x_axis_label = 'year', y_axis_label = 'life_expectancy')

legend_items = []
for country in scandinavians:
    color = next(colors)
    is_country = europe['country'] == country
    r = fig.line(europe[is_country]['year'],
             europe[is_country]['lifeExp'],
             line_width=2,
             color=color, alpha=1.0,
             muted_color=color, muted_alpha=0.2)
    legend_items.append((country, [r]))
    
legend = Legend(items=legend_items, location=(20, 440))
legend.click_policy = "mute"
fig.add_layout(legend, "right")
    
show(fig)<jupyter_output><empty_output><jupyter_text>Bar chartsTo illustrate bar charts we'll look at the GDP in Scandinavia over the years.<jupyter_code>from bokeh.models import ColumnDataSource, FactorRange
from bokeh.palettes import Category20_20 as palette
from bokeh.transform import factor_cmap

years = [str(year) for year in list(europe['year'].unique())]
data = scandinavia[['country', 'year', 'gdpPercap']]

data = scandinavia.to_dict(orient='list')
x = [(year, country) for country in scandinavians for year in years]
data['x'] = x


fig = figure(x_range=FactorRange(*x), plot_height=250, title="Gapminder data",
           toolbar_location=None, tools="")
fig.vbar(x='x', top='gdpPercap', width=0.8, source=data,
        fill_color=factor_cmap('x', palette=palette, factors=scandinavians, start=1, end=2))

fig.xaxis.major_label_orientation = 1
    
show(fig)<jupyter_output><empty_output><jupyter_text>Bubble plotsTo illustrate scatter plots we'll look at life expectancy vs. income per country, where we'll scale the bubble by population size. This is the most well known graphic by Gapminder.<jupyter_code>from ipywidgets import interact, widgets
from bokeh.io import curdoc, output_notebook, push_notebook
from bokeh.layouts import layout
from bokeh.models import (Button, CategoricalColorMapper, ColumnDataSource,
                          HoverTool, Label, SingleIntervalTicker, Slider,)
from bokeh.palettes import Spectral6
from bokeh.plotting import figure

output_notebook()

years = df['year'].unique()

plot = figure(x_range=(0, 40000), y_range=(25, 90), title='Gapminder Data', plot_height=300)
plot.xaxis.ticker = SingleIntervalTicker(interval=5000)
plot.xaxis.axis_label = "GDP per capita"
plot.yaxis.ticker = SingleIntervalTicker(interval=20)
plot.yaxis.axis_label = "Life expectancy"

label = Label(x=1.1, y=23, text=str(years[0]), text_font_size='93px', text_color='#eeeeee')
plot.add_layout(label)

is_year = df['year'] == years[0]
source = ColumnDataSource(data=df[is_year])

color_mapper = CategoricalColorMapper(palette=Spectral6, factors=df['continent'].unique())
plot.circle(
    x='gdpPercap',
    y='lifeExp',
    size=10,
    source=source,
    fill_color={'field': 'continent', 'transform': color_mapper},
    fill_alpha=0.8,
    line_color='#7c7e71',
    line_width=0.5,
    line_alpha=0.5,
    legend_group='continent',
)
plot.add_tools(HoverTool(tooltips="@country", show_arrow=False, point_policy='follow_mouse'))


def slider_update(year):
    label.text = str(year)
    is_year = df['year'] == year
    source.data = df[is_year]
    push_notebook()

show(plot, notebook_handle=True)
interact(slider_update, year=widgets.IntSlider(min=years[0], max=years[-1], step=5, value=years[0]))<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1189920671955203, 'fraction_numerical': 0.017421060818167678, 'mean_word_length': 5.07176581680831, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 25, 'https://': 1, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '6', 'dir': 'jupyter-structured-clean-dedup', 'id': '582853', 'license': 'BSD-3-Clause', 'n_tokens_mistral': 2281, 'n_tokens_neox': 2149, 'n_words': 529, 'path': 'L03_visualisation/L03-2_interactive_plots_bokeh.ipynb', 'repo_name': 'akdiem/sc_sintef_advanced_python_course', 'size': '6429'}