import param
import numpy as np 
import pandas as pd
import panel as pn

import altair as alt
import plotly.graph_objs as go
import as pio
import matplotlib.pyplot as plt

pn.extension('vega', 'plotly', defer_load=True, template='fast')
import hvplot.pandas


Let us start by configuring some high-level variables and configure the template:

XLABEL = 'GDP per capita (2000 dollars)'
YLABEL = 'Life expectancy (years)'
YLIM = (20, 90)
ACCENT = "#00A170"

PERIOD = 1000 # milliseconds

    title="Hans Rosling's Gapminder",

Extract the dataset#

First, we’ll get the data into a Pandas dataframe. We use the built in cache to speed up the app.

def get_dataset():
    url = ''
    return pd.read_csv(url)

dataset = get_dataset()

YEARS = [int(year) for year in dataset.year.unique()]

country year pop continent lifeExp gdpPercap
906 Libya 1982 3344074.0 Africa 62.155 17364.275380
1441 Sudan 1957 9753392.0 Africa 39.624 1770.337074
12 Albania 1952 1282697.0 Europe 55.230 1601.056136
84 Bahrain 1952 120447.0 Asia 50.939 9867.084765
1064 Namibia 1992 1554253.0 Africa 61.999 3804.537999
944 Malaysia 1992 18319502.0 Asia 70.693 7277.912802
607 Guatemala 1987 7326406.0 Americas 60.782 4246.485974
1642 Venezuela 2002 24287670.0 Americas 72.766 8605.047831
902 Libya 1962 1441863.0 Africa 47.808 6757.030816
1196 Paraguay 1992 4483945.0 Americas 68.225 4196.411078

Set up widgets and description#

Next we will set up a periodic callback to allow cycling through the years, set up the widgets to control the application and write an introduction:

def play():
    if year.value == YEARS[-1]:
        year.value = YEARS[0]

    index = YEARS.index(year.value)
    year.value = YEARS[index+1]    

year = pn.widgets.DiscreteSlider(
    value=YEARS[-1], options=YEARS, name="Year", width=280
show_legend = pn.widgets.Checkbox(value=True, name="Show Legend")

periodic_callback = pn.state.add_periodic_callback(play, start=False, period=PERIOD)
player = pn.widgets.Checkbox.from_param(periodic_callback.param.running, name="Autoplay")

widgets = pn.Column(year, player, show_legend, margin=(0,15))

desc = """## 🎓 Info

The [Panel]( library from [HoloViz](
lets you make widget-controlled apps and dashboards from a wide variety of 
plotting libraries and data types. Here you can try out four different plotting libraries
controlled by a couple of widgets, for Hans Rosling's 
[gapminder]( example.

Source: [pyviz-topics - gapminder](

settings = pn.Column(
    "## ⚙️ Settings", widgets, desc,


Define plotting functions#

Now let’s define helper functions and functions to plot this dataset with Matplotlib, Plotly, Altair, and hvPlot (using HoloViews and Bokeh).

def get_data(year):
    df = dataset[(dataset.year==year) & (dataset.gdpPercap < 10000)].copy()
    df['size'] = np.sqrt(df['pop']*2.666051223553066e-05)
    df['size_hvplot'] = df['size']*6
    return df

def get_title(library, year):
    return f"{library}: Life expectancy vs. GDP, {year}"

def get_xlim(data):
    return (data['gdpPercap'].min()-100,data['gdpPercap'].max()+1000)

def mpl_view(year=1952, show_legend=True):
    data = get_data(year)
    title = get_title("Matplotlib", year)
    xlim = get_xlim(data)

    plot = plt.figure(figsize=(10, 6), facecolor=(0, 0, 0, 0))
    ax = plot.add_subplot(111)

    for continent, df in data.groupby('continent'):
        ax.scatter(df.gdpPercap, y=df.lifeExp, s=df['size']*5,
                   edgecolor='black', label=continent)

    if show_legend:

    return plot

pio.templates.default = None

def plotly_view(year=1952, show_legend=True):
    data = get_data(year)
    title = get_title("Plotly", year)
    xlim = get_xlim(data)

    traces = []
    for continent, df in data.groupby('continent'):
        marker=dict(symbol='circle', sizemode='area', sizeref=0.1, size=df['size'], line=dict(width=2))
        traces.append(go.Scatter(x=df.gdpPercap, y=df.lifeExp, mode='markers', marker=marker, name=continent,

    axis_opts = dict(gridcolor='rgb(255, 255, 255)', zerolinewidth=1, ticklen=5, gridwidth=2)
    layout = go.Layout(
        title=title, showlegend=show_legend,
        xaxis=dict(title=XLABEL, type='log', **axis_opts),
        yaxis=dict(title=YLABEL, **axis_opts),
        autosize=True, paper_bgcolor='rgba(0,0,0,0)',
    return go.Figure(data=traces, layout=layout)

def altair_view(year=1952, show_legend=True, height="container", width="container"):
    data = get_data(year)
    title = get_title("Altair/ Vega", year)
    xlim = get_xlim(data)
    legend= ({} if show_legend else {'legend': None})
    return (
                alt.X('gdpPercap:Q', scale=alt.Scale(type='log'), axis=alt.Axis(title=XLABEL)),
                alt.Y('lifeExp:Q', scale=alt.Scale(zero=False, domain=YLIM), axis=alt.Axis(title=YLABEL)),
                size=alt.Size('pop:Q', scale=alt.Scale(type="log"), legend=None),
                color=alt.Color('continent', scale=alt.Scale(scheme="category10"), **legend),
            .properties(title=title, height=height, width=width, background='rgba(0,0,0,0)') 

def hvplot_view(year=1952, show_legend=True):
    data = get_data(year)
    title = get_title("hvPlot/ Bokeh", year)
    xlim = get_xlim(data)
    return data.hvplot.scatter(
        'gdpPercap', 'lifeExp', by='continent', s='size_hvplot', alpha=0.8,
        logx=True, title=title, responsive=True, legend='bottom_right',
        hover_cols=['country'], ylim=YLIM, xlim=xlim, ylabel=YLABEL, xlabel=XLABEL

Bind the plot functions to the widgets#

mpl_view    = pn.bind(mpl_view,    year=year, show_legend=show_legend)
plotly_view = pn.bind(plotly_view, year=year, show_legend=show_legend)
altair_view = pn.bind(altair_view, year=year, show_legend=show_legend)
hvplot_view = pn.bind(hvplot_view, year=year, show_legend=show_legend)

plots = pn.layout.GridBox(
    pn.pane.Matplotlib(mpl_view, format='png', sizing_mode='scale_both', tight=True, margin=10),
    pn.pane.HoloViews(hvplot_view, sizing_mode='stretch_both', margin=10),
    pn.pane.Plotly(plotly_view, sizing_mode='stretch_both', margin=10),
    pn.pane.Vega(altair_view, sizing_mode='stretch_both', margin=10),