Creating Interactive Dashboards from Jupyter Notebooks
Posted by Duarte O.Carmo in articles
Introduction
I am pleased to have another guest post from Duarte O.Carmo. He wrote series of posts in July on report generation with Papermill that were very well received. In this article, he will explore how to use Voilà and Plotly Express to convert a Jupyter notebook into a standalone interactive web site. In addition, this article will show examples of collecting data through an API endpoint, performing sentiment analysis on that data and show multiple approaches to deploying the dashboard.
About Duarte
Hey everyone! My name is Duarte O.Carmo and I’m a Consultant working
at Jabra that loves working with python and data. Make sure to visit my
website if you want to find more about me 
Since this is a long article, here are the table of contents for easier navigation:
The Goal
Jupyter notebooks are one of my favorite tools to work with data, they are simple to use, fast to set up, and flexible. However, they do have their disadvantages: source control, collaboration, and reproducibility are just some of them. As I illustrated in my prior post, I tend to enjoy seeing what I can accomplish with them.
An increasing need is the sharing of our notebooks. Sure, you can export your notebooks to html, pdf, or even use something like nbviewer to share them. But what if your data changes constantly? What if every time you run your notebook, you expect to see something different? How can you go about sharing something like that?
But what if your data changes constantly? What if every time you run your notebook, you expect to see something different? How can you go about sharing something like that?
In this article, I’ll show you how to create a Jupyter Notebook that fetches live data, builds an interactive plot and then how to deploy it as a live dashboard. When you want to share the dashboard, all you need to share with someone is a link.
Let’s have some fun with the data first.
Getting live Reddit data
We will use Reddit as the source of data for our dashboard. Reddit is a tremendous source of information, and there are a million ways to get access to it. One of my favorite ways to access the data is through a small API called pushshift. The documentation is right here.
Let’s say you wanted the most recent comments mentioning the word “python”. In python, you could use requests to get a json version of the data:
import requests
url = "https://api.pushshift.io/reddit/search/comment/?q=python"
request = requests.get(url)
json_response = request.json()
You can add a multitude of parameters to this request, such as:
- in a certain subreddit
- after a certain day
- sorted by up votes
- many more
To make my life easier, I built a function that allows me to call this API as a function:
def get_pushshift_data(data_type, **kwargs):
"""
Gets data from the pushshift api.
data_type can be 'comment' or 'submission'
The rest of the args are interpreted as payload.
Read more: https://github.com/pushshift/api
"""
base_url = f"https://api.pushshift.io/reddit/search/{data_type}/"
payload = kwargs
request = requests.get(base_url, params=payload)
return request.json()
Using the
payload
parameter and
kwargs
I can then add any payload I wish as a function. For example,
get_pushshift_data(data_type="comment", # give me comments
q="python", # that mention 'python'
after="48h", # in the last 48 hours
size=1000, # maximum 1000 comments
sort_type="score", # sort them by score
sort="desc") # sort descending
returns the json response. Pretty sweet right?
Analyzing the data with Plotly Express
In what subreddits does the word ‘python’ appear more?
To answer the above question, we start by getting the data with our function:
data = get_pushshift_data(data_type="comment",
q="python",
after="48h",
size=1000,
aggs="subreddit")
The
aggs
keyword asks pushshift to return an aggregation into subreddits, which basically means, group the results by subreddit.
(read about it in the documentation)
Since the json response is pretty nested, we’ll need to navigate a bit inside of the dictionary.
data = data.get("aggs").get("subreddit")
And we transform the list of dictionaries returned into a pandas DataFrame, and get the top 10.
df = pandas.DataFrame.from_records(data)[0:10]
Here’s what our DataFrame looks like:
| doc_count | key | |
|---|---|---|
| 0 | 352 | learnpython |
| 1 | 220 | AskReddit |
| 2 | 177 | Python |
| 3 | 139 | learnprogramming |
These are the names of the subreddits where the word
python
appears most frequently in their comments
!
Let’s plot our results with the Ploty Express library. Plotly Express is great, in my opinion, if you want to:
- create figures quickly.

- create figures that are a bit more interactive than matplotlib.

- don’t mind a bit more installation and (imo) a bit less documentation.

Here’s all the code you need:
import plotly.express as px
px.bar(df, # our dataframe
x="key", # x will be the 'key' column of the dataframe
y="doc_count", # y will be the 'doc_count' column of the dataframe
title=f"Subreddits with most activity - comments with 'python' in the last 48h",
labels={"doc_count": "# comments","key": "Subreddits"}, # the axis names
color_discrete_sequence=["blueviolet"], # the colors used
height=500,
width=800)
Yes, perhaps a bit more verbose than matplotlib, but you get an interactive chart!
All of the details are included in the notebook for this article.
What are the most up-voted comments with the word ‘python’?
To answer this question, our function will again come in handy. Let’s aggregate things a bit.
Don’t get scared, this is a one liner that will produce similar results to above:
# get the data we need using the function
data = get_pushshift_data(data_type="comment", q="python", after="7d", size=10, sort_type="score", sort="desc").get("data")
# we only care about certain columns
df = pandas.DataFrame.from_records(data)[["author", "subreddit", "score", "body", "permalink"]]
# we only keep the first X characters of the body of the comment (sometimes they are too big)
df['body'] = df['body'].str[0:400] + "..."
# we append the string to all the permalink entries so that we have a link to the comment
df['permalink'] = "https://reddit.com" + df['permalink'].astype(str)
# style the last column to be clickable and print
df.style.format({'permalink': make_clickable})
To make a DataFrame column clickable you can can apply the following function to it:
def make_clickable(val):
""" Makes a pandas column clickable by wrapping it in some html.
"""
return '<a href="{}">Link</a>'.format(val,val)
The above code will return the top 10 most upvoted comments of the last 7 days: