Jupyter Notebooks for Dashboards

Authors
Dr. Sangeetha Nandakumar | Dr. Nicholas Del Grosso

Setup

Import Libraries

import panel as pn
pn.extension()

import pandas as pd
import hvplot.pandas
import panel.widgets as pnw

Download Data

import os
import owncloud

if not os.path.exists('data'):
    print('Creating directory for data')
    os.mkdir('data')

# Download steinmetz_winter2017.csv
if not os.path.exists('data/steinmetz_winter2017.csv'):
    oc = owncloud.Client.from_public_link('https://uni-bonn.sciebo.de/s/G5rdvTsoESXolF4')
    oc.get_file('/', 'data/steinmetz_winter2017.csv')

# Download steinmetz_winter2016.csv
if not os.path.exists('data/steinmetz_winter2016.csv'):
    oc = owncloud.Client.from_public_link('https://uni-bonn.sciebo.de/s/xKAG9nqHyWmXBBI')
    oc.get_file('/', 'data/steinmetz_winter2016.csv')

# Download steinmetz_summer2017.csv
if not os.path.exists('data/steinmetz_summer2017.csv'):
    oc = owncloud.Client.from_public_link('https://uni-bonn.sciebo.de/s/XLDoTQQoDdFLhlz')
    oc.get_file('/', 'data/steinmetz_summer2017.csv')

As researchers, we often need to visualize and present our findings in an engaging way. While code is important for analysis, we do not always want to show it all the time as our results are often data-centric and not code-centric. Dashboards can help us interact with and explore data in real-time, highlighting important insights. In this notebook, we will explore the process of designing interactive layouts and integrating widgets in Jupyter notebooks using Panel.

Section 1: Explorer For Quick-Look Of Data

Many Python plotting libraries that support interactive dashboard building are built to work with Jupyter notebooks because notebooks render dynamic visualizations directly within the notebook interface. It allows for real-time interaction with the data through widgets and sliders, enabling users to explore and analyze data. These interactive visualization update when parameters are tweaked.

We first explore capabilities of notebook to render interactive elements by making use of hvplot’s explorer method.

Code Description
df1 = pd.read_csv(file) Reads a CSV file into a Pandas DataFrame and assigns it to df1.
df1[[column1]].hvplot.explorer() Plots an explorer view (interactive visualization) for column1
df1[[column1, column2]].hvplot.explorer() Plots an explorer view (interactive visualization) for column1 and column2

Exercises

Example: Plot a histogram of feedback times from Winter 2016 dataset using explorer’s interactive feature.

df1 = pd.read_csv('data/steinmetz_winter2016.csv')
df1[["feedback_time"]].hvplot.explorer()

Exercise: Plot a histogram of feedback times from Winter 2017 dataset using explorer’s interactive feature.

Solution
df2 = pd.read_csv('data/steinmetz_winter2017.csv')
df2[["feedback_time"]].hvplot.explorer()

Exercise: Plot a histogram of feebdack times of Summer 2017 dataset using explorer’s interactive feature.

Solution
df3 = pd.read_csv('data/steinmetz_summer2017.csv')
df3[["feedback_time"]].hvplot.explorer()

Example: Plot a scatter plot of feedback time with response time of Winter 2016. Add a suitable title

df1 = pd.read_csv('data/steinmetz_winter2016.csv')
df1[["response_time", "feedback_time"]].hvplot.explorer()

Exercise: Plot a scatter plot of feedback time with response time of Winter 2017. Change X and Y labels.

Solution
df2 = pd.read_csv('data/steinmetz_winter2017.csv')
df2[["response_time", "feedback_time"]].hvplot.explorer()

Exercise: Plot a scatter plot of feedback time with response time of Summer 2017. See what is in the Code tab.

Solution
df3 = pd.read_csv('data/steinmetz_summer2017.csv')
df3[["response_time", "feedback_time"]].hvplot.explorer()

Example: Plot a box plot of response times of Winter 2016 data split by response_type. Select response_type in the By section

df1 = pd.read_csv('data/steinmetz_winter2016.csv')
df1[["response_type", "response_time", "feedback_time"]].hvplot.explorer()

Exercise: Plot a box plot of feedback times of Winter 2017 data split by response_type.

Solution
df2 = pd.read_csv('data/steinmetz_winter2017.csv')
df2[["response_type", "response_time", "feedback_time"]].hvplot.explorer()

Exercise: Plot a box plot of feedback times of Summer 2017 data split by feedback_type.

Solution
df3 = pd.read_csv('data/steinmetz_summer2017.csv')
df3[["feedback_type", "feedback_time"]].hvplot.explorer()

Example: Plot a box plot of response times of a response types selected from slider of Winter 2016 data. Use Groupby

df1 = pd.read_csv('data/steinmetz_winter2016.csv')
df1[["mouse", "response_type", "response_time", "feedback_time"]].hvplot.explorer()

Exercise: Plot a box plot of feedback times of a mouse selected from drop down menu of Winter 2017 data.

Solution
df2 = pd.read_csv('data/steinmetz_winter2017.csv')
df2[["mouse", "response_type", "response_time", "feedback_time"]].hvplot.explorer()

Exercise: Plot a box plot of feedback times of a mouse selected from drop down menu of Winter 2017 data and split by feedback types.

Solution
df2 = pd.read_csv('data/steinmetz_winter2017.csv')
df2[["mouse", "response_type", "response_time", "feedback_time"]].hvplot.explorer()

Section 2: Dashboard Building Process in Notebook

While building dashboards, components like tables and plots are arranged in a layout in rows or columns. Let’s get some practice building dashboards in notebooks using panel.

Code Description
df1[cols].head(5) Selects the first 5 rows of the specified columns from df1
pn.Row(element1, element2, element3) Creates a Panel layout displaying the three elements (element1, element2, and element3) in a horizontal row.
pn.Column(element1, element2, element3) Creates a Panel layout displaying the three elements (element1, element2, and element3) in a vertical column.
row1 = df1["response_time"].hvplot.hist() + df2["response_time"].hvplot.hist() + df3["response_time"].hvplot.hist() Combines histograms for response_time from df1, df2, and df3 into one row layout using hvPlot.
dashboard_1.servable() Makes dashboard_1 dashboard interactive and ready to be served in a Panel app.
dashboard_1.clear() Clears the layout or any cached data from dashboard_1.

Exercises

df1 = pd.read_csv('data/steinmetz_winter2016.csv')
df2 = pd.read_csv('data/steinmetz_winter2017.csv')
df3 = pd.read_csv('data/steinmetz_summer2017.csv')

Example: Show top 5 rows of mouse, feedback and response times, and response type columns of all three datasets in a row.

cols = ["mouse", "feedback_time", "response_time", "response_type"]
element1 = df1[cols].head(5)
element2 = df2[cols].head(5)
element3 = df3[cols].head(5)
pn.Row(element1, element2, element3)

Exercise: Show top 3 rows of mouse, feedback and response times, and response type columns of all three datasets in a row.

Solution
cols = ["mouse", "feedback_time", "response_time", "response_type"]
element1 = df1[cols].head(3)
element2 = df2[cols].head(3)
element3 = df3[cols].head(3)
pn.Row(element1, element2, element3)

Exercise: Show top 3 rows of mouse, feedback and response times, and response type columns of all three datasets in a column.

Solution
cols = ["mouse", "feedback_time", "response_time", "response_type"]
element1 = df1[cols].head(3)
element2 = df2[cols].head(3)
element3 = df3[cols].head(3)
pn.Column(element1, element2, element3)

Example: Plot histogram of response_times of all three datasets in a row.

element1 = df1["response_time"].hvplot.hist()
element2 = df2["response_time"].hvplot.hist()
element3 = df3["response_time"].hvplot.hist()
pn.Row(element1, element2, element3)

Exercise: Plot histogram of feedback_times of all three datasets in a row.

Solution
element1 = df1["feedback_time"].hvplot.hist()
element2 = df2["feedback_time"].hvplot.hist()
element3 = df3["feedback_time"].hvplot.hist()
pn.Row(element1, element2, element3)

Exercise: Plot histogram of response_times of all three datasets in a Column.

Solution
element1 = df1["response_time"].hvplot.hist()
element2 = df2["response_time"].hvplot.hist()
element3 = df3["response_time"].hvplot.hist()
pn.Column(element1, element2, element3)

Demo Arrange histograms of Winter 2016, 2017, Summer 2017 response_times in rows. In another row, arrange feedback time histograms.

row1 = df1["response_time"].hvplot.hist() + df2["response_time"].hvplot.hist() + df3["response_time"].hvplot.hist()
row2 = df1["feedback_time"].hvplot.hist() + df2["feedback_time"].hvplot.hist() + df3["feedback_time"].hvplot.hist()
pn.Column(row1, row2)

Example: Plot histogram of response_times of all three datasets in a row and Preview with Panel.

element1 = df1["response_time"].hvplot.hist()
element2 = df2["response_time"].hvplot.hist()
element3 = df3["response_time"].hvplot.hist()
dashboard_1 = pn.Row(element1, element2, element3)
dashboard_1.servable()
dashboard_1.clear();

Plot histogram of response_time of all three datasets in a column and Preview with Panel.

element1 = df1["response_time"].hvplot.hist()
element2 = df2["response_time"].hvplot.hist()
element3 = df3["response_time"].hvplot.hist()
dashboard_1 = pn.Column(element1, element2, element3)
dashboard_1.servable()
dashboard_1.clear();

Example: Plot histogram of feedback_time of all three datasets in a column and Preview with Panel.

element1 = df1["feedback_time"].hvplot.hist()
element2 = df2["feedback_time"].hvplot.hist()
element3 = df3["feedback_time"].hvplot.hist()
dashboard_1 = pn.Column(element1, element2, element3)
dashboard_1.servable()
dashboard_1.clear();

Demo Arrange histograms of Winter 2016, 2017, Summer 2017 response_times in rows. In another row, arrange feedback time histograms. Preview with Panel.

row1 = df1["response_time"].hvplot.hist() + df2["response_time"].hvplot.hist() + df3["response_time"].hvplot.hist()
row2 = df1["feedback_time"].hvplot.hist() + df2["feedback_time"].hvplot.hist() + df3["feedback_time"].hvplot.hist()
dashboard_3 = pn.Column(row1, row2)
dashboard_3.servable();
dashboard_3.clear();

Section 3: Adding Interactivity with Dashboard

panel and hvplot have enabled creating and testing interactive features in the notebook directly. In this section, let’s see how to do that.

Code Description
dashboard.servable() Makes dashboard dashboard interactive and ready to be served in a Panel app.
dashboard.clear() Clears the layout or any cached data from dashboard.
select = pnw.Select(name='Select', options=['response_time', 'feedback_time']) Creates a dropdown select widget with response_time and feedback_time as options.
interactive_stat_df1 = df1.interactive() Makes df1 an interactive DataFrame for real-time updates.
stats_1 = interactive_stat_df1[select].describe() Generates descriptive statistics for the selected column in df1.
slider = pnw.IntSlider(name='Num Rows', start=0, end=10) Creates an integer slider widget with a range of 0 to 10 to control the number of rows displayed.
table_1 = interactive_df1.head(slider) Displays the first slider number of rows from df1 interactively.

Exercises

Example: Plot a row of histograms of response_time and feedback_time grouped by mouse of df1

cols = ["response_time", "feedback_time", "mouse"]
plot_1 = df1.hvplot.hist('response_time', groupby='mouse')
plot_2 = df1.hvplot.hist('feedback_time', groupby='mouse')
i_dashboard_1 = pn.Row(plot_1, plot_2)
i_dashboard_1.servable();
i_dashboard_1.clear();

Exercise: Plot a row of histograms of response_time grouped by mouse of df1 and df2

Solution
cols = ["response_time", "feedback_time", "mouse"]
plot_1 = df1.hvplot.hist('response_time', groupby='mouse')
plot_2 = df2.hvplot.hist('response_time', groupby='mouse')
i_dashboard_2 = pn.Row(plot_1, plot_2)
i_dashboard_2.servable();
i_dashboard_2.clear();

Exercise: Plot columns of scatter plots of (response time, feedback time) grouped by mouse for df1, df2, and df3

Solution
cols = ["response_time", "feedback_time", "mouse"]
plot_1 = df1.hvplot.scatter('response_time', 'feedback_time', groupby='mouse')
plot_2 = df2.hvplot.scatter('response_time', 'feedback_time', groupby='mouse')
plot_3 = df3.hvplot.scatter('response_time', 'feedback_time', groupby='mouse')

i_dashboard_3 = pn.Row(plot_1, plot_2, plot_3)
i_dashboard_3.servable();
i_dashboard_3.clear();

Example: Create an interactive Panel dashboard that allows users to select either the response_time or feedback_time column from two DataFrames (df1 and df2) via a dropdown, and displays the corresponding descriptive statistics for both DataFrames side by side.

select = pnw.Select(name='Select', options=['response_time','feedback_time'])

interactive_stat_df1 = df1.interactive()
interactive_stat_df2 = df2.interactive()

stats_1 = interactive_stat_df1[select].describe()
stats_2 = interactive_stat_df2[select].describe()
ip_stats_dashboard_1 = pn.Row(stats_1, stats_2)
ip_stats_dashboard_1.servable();
ip_stats_dashboard_1.clear();

Exercise: Create an interactive Panel dashboard that allows users to select either the response_time or feedback_time column from two DataFrames (df1 and df3) via a dropdown, and display the corresponding descriptive statistics for both DataFrames in a column layout.

Solution
select = pnw.Select(name='Select', options=['response_time','feedback_time'])

interactive_stat_df1 = df1.interactive()
interactive_stat_df3 = df3.interactive()

stats_1 = interactive_stat_df1[select].describe()
stats_3 = interactive_stat_df3[select].describe()
ip_stats_dashboard_2 = pn.Row(stats_1, stats_3)
ip_stats_dashboard_2.servable();
ip_stats_dashboard_2.clear();

Exercise: Create an interactive Panel dashboard that allows users to select either the response_time or feedback_time column from three DataFrames (df1, df2, and df3) via a dropdown, and display the corresponding descriptive statistics for all three DataFrames side by side.

Solution
select = pnw.Select(name='Select', options=['response_time','feedback_time'])

interactive_stat_df1 = df1.interactive()
interactive_stat_df2 = df2.interactive()
interactive_stat_df3 = df3.interactive()

stats_1 = interactive_stat_df1[select].describe()
stats_2 = interactive_stat_df2[select].describe()
stats_3 = interactive_stat_df3[select].describe()
ip_stats_dashboard_3 = pn.Row(stats_1, stats_2, stats_3)
ip_stats_dashboard_3.servable();
ip_stats_dashboard_3.clear();

Example: Create an interactive Panel dashboard with an integer slider that allows users to select the number of rows (between 0 and 10) to display from two DataFrames (df1 and df2), and show the selected rows side by side.

slider = pnw.IntSlider(name='Num Rows', start=0, end=10)

interactive_df1 = df1.interactive()
interactive_df2 = df2.interactive()

table_1 = interactive_df1.head(slider)
table_2 = interactive_df2.head(slider)
ip_data_dashboard_1 = pn.Row(table_1, table_2)
ip_data_dashboard_1.servable();
ip_data_dashboard_1.clear();

Exercise: Create an interactive Panel dashboard with an integer slider that allows users to select the number of rows (between 0 and 3) to display from two DataFrames (df1 and df2), and display the selected rows from both DataFrames in a column layout.

Solution
slider = pnw.IntSlider(name='Num Rows', start=0, end=3)

interactive_df1 = df1.interactive()
interactive_df2 = df2.interactive()

table_1 = interactive_df1.head(slider)
table_2 = interactive_df2.head(slider)
ip_data_dashboard_2 = pn.Row(table_1, table_2)
ip_data_dashboard_2.servable();
ip_data_dashboard_2.clear();

Exercise: Create an interactive Panel dashboard with an integer slider that allows users to select the number of rows (between 1 and 10) to display from three DataFrames (df1, df2, and df3), and display the selected rows from all three DataFrames in a column layout.

Solution
slider = pnw.IntSlider(name='Num Rows', start=0, end=3)

interactive_df1 = df1.interactive()
interactive_df2 = df2.interactive()
interactive_df3 = df3.interactive()

table_1 = interactive_df1.head(slider)
table_2 = interactive_df2.head(slider)
table_3 = interactive_df3.head(slider)

ip_data_dashboard_3 = pn.Row(table_1, table_2)
ip_data_dashboard_3.servable();
ip_data_dashboard_3.clear();

Section 4: Serving Dashboard from Terminal

In the terminal type

  1. Navigate to the notebook directory e.g. cd Day1/
  2. Serve the app
panel serve 03_Dashboards.ipynb
  1. In the terminal, you will see a link next to Bokeh app running at. If you click on it, you can see the app on your browser.
df1 = pd.read_csv('data/steinmetz_winter2016.csv')

select = pnw.Select(name='Select', options=['response_time','feedback_time'])

interactive_stat_df1 = df1.interactive()

stats_1 = interactive_stat_df1[select].describe()
ip_stats_dashboard = pn.Column("Winter 2016 - Response Time", stats_1)
ip_stats_dashboard.servable();
ip_stats_dashboard.clear();