Creating Interactive Dashboards in Python: A Tutorial using Streamlit

Jess Gillam
Data science at Nesta
10 min readMay 18, 2023

This article has been co-written by Jess Gillam and Lizzie Ingram.

šŸ“¢ News claxon šŸ“¢ ā€” you no longer need to be (or hire) a web developer to create beautiful applications or dashboards! Streamlit is a free, open-source framework that enables the creation of visually-appealing and interactive web-based apps for data analysis and machine learning. It is a Python-library that makes the process of app creation quick and simple, allowing users to repurpose pre-existing Python code and create handy functionalities with just a few lines of code.

In this blog we will go through the steps needed to set-up a Streamlit app using the example of an app we created to view and analyse Indices of Deprivation (IoD) (2019) data (password = Nest@IoD). By the end of this tutorial you will know how to: set up the basic app, add text, add Vega-Altair plots, add selections, add sidebars, add a menu, add a password and more! This is the second blog in a series, the first takes you through creating interactive Vega-Altair plots.

Introduction to the data

For those interested in the data used for this tutorial, the IoD data are publicly available and widely used data that measures relative deprivation in small areas across England, also known as Lower Super Output Areas (LSOAs). It ranks small areas, which have an average population of 1,500 people, from the 1st most deprived area to the 32,844th least deprived. To get an overall Index of Multiple Deprivation (IMD), the index combines seven different indices of deprivation, each of which have different weightings: income (22.5%), employment (22.5%), education (13.5%), health (13.5%), crime (13.5%), barriers to housing and services (13.5%) and living environment (13.5% weighting). The latest IoD data in England was published in 2019. An equivalent index exists for Wales, Scotland and Northern Ireland, albeit with slight differences in how it is measured and calculated.

Setting up a basic app

Letā€™s get started! Before adding any figures or more complex functionalities, the first thing you need to do is to install the Streamlit Python library. To do this, go to your Terminal and type the following:

pip install streamlit
#Alternatively, if you use conda environments:
conda install -c conda-forge streamlit

Next, you need to create a new Python file in the directory in which you want the app to be located. To import the Streamlit Python library into your code, you then need to type the following:

import streamlit as st 
#Plus other packages you want to include, for our example we need:
from PIL import Image #To use images in the app
import altair as alt #To add altair visualisations of the data
import pandas as pd #For simple data manipulation

Now letā€™s start building the app! First, you may want to add a favicon (a website icon) and a title which will appear in the tab of your web browser. The code to do this is below, where the ā€œpath_to_imageā€ is your local path to the image you want to have as a favicon.

# Load the favicon and set the page config (so what appears in the tab on your web browser)
im = Image.open("path_to_image")
st.set_page_config(page_title="IoD Deciles across England", layout="wide", page_icon=im)

Now that you have set up the page, you might want to add a title within the app.

st.title("Geographical Analysis of the IoD Deciles Across England")

If you want to add images you can use st.image(). In this app we wanted to add the Nesta logo, and we did this using the following code:

logo = Image.open("images/nesta_logo.png")
st.image(logo, width=250)

Letā€™s check everything works as expected! To run the app locally on your computer, go to your terminal and navigate to the directory with your app. Then type the following (replacing name_of_app with your own file name!):

streamlit run name_of_app.py

This should open the app in a web browser, where you can check everything is working as you expect. One neat trick of Streamlit is that, when you make an update to the code and save it, it will automatically register the changes! You should be able to see a ā€˜Rerunā€™ button in the top right corner of the web browser to view the newest version of the app (see Figure 1).

Figure 1: A walk through of how to rerun your app to register and view any changes.

Adding text to your app

You can include text in Streamlit in a couple of different ways. If you want to write some simple text, you can use st.write(ā€œinsert_text_hereā€). Alternatively, you can also format strings as markdown. This allows you to do things such as add hyperlinks to text and use html code!

# Example of how to use markdown:
url_link = ā€œlink_to_urlā€
st.markdown(
f"<div style='text-align: center;'>Taken from the infographic <a href={url_link}> here</a>. </div>",
unsafe_allow_html=True, #This allows you to use html code!
)

How to load in data

You are also able to pull in data from your local directory in Streamlit, as you would expect. For example:

data = pd.read_csv('path_to_file.csv')

Loaded data can then be used to create interactive plots. In the next section, we give an example of how to use Vega-Altair figures in a Streamlit app that relies on loaded-in data. Vega-Altair is a data visualisation library for Python that enables users to create attractive and engaging data visualisations. We regularly use Vega-Altair at Nesta to share the results of our data analyses with stakeholders and the public, and have previously described how and why we use Vega-Altair in the previous blog in this series.

When plotting maps in Streamlit, due to an interaction between Vega-Altair and Streamlit, you may have to load your data in through a URL instead of locally. One simple way to load in geographical data is to use a public github repository and load it in as a JSON or GEOJSON file. The code to do this is as follows:

geojson_la = "https://raw.githubusercontent.com/dap_medium_articles/dev/streamlit_app_tutorial/shapefiles/la_clean_shapefiles_2019.geojson"
geodata_la = alt.Data(
url=geojson_la, format=alt.DataFormat(property="features", type="json")
)

Adding in Vega-Altair plots

Vega-Altair plots are very easy to bring into Streamlit. Say you create a plot, which you call ā€˜combined_chartā€™, you can plot this in Streamlit by typing:

st.altair_chart(combined_chart)

This blog will not cover how to add figures and images created in other Python libraries to a Streamlit app. For more information on this, see the Streamlit documentation here.

Adding in selections

One really great feature of Streamlit is that it allows users to select what they want to view from single-option drop down boxes and multiple-option select boxes. This can allow users to filter and then explore the data, e.g. in plots. In our example weā€™re able to filter maps to look at specific regions of England.

You could do this using the following code:

region_filter = [
"North East",
"North West",
"Yorkshire and The Humber",
"East Midlands",
"West Midlands",
"South West",
"East",
"South East",
"London",
]
region_selection = st.selectbox(
"To look in closer detail, choose a region of England:",
options=sorted(region_filter),
)

You can then use region_selection to filter your dataframe, e.g.

data = data[data.region==region_selection]

Then you can plot the data with your chosen visualisation tool. We show an example of how this is visualised in the Streamlit app in Figure 2 below.

Figure 2: A short GIF to illustrate how Streamlit single-select drop down boxes can enable one to filter data for plotting on a choropleth map.

Similarly, you can select multiple options. For example, if you have a list of local authorities (all_las):

la_compare_select = st.multiselect(
"Choose up to five LAs:",
options=sorted(all_las),
default=None,
max_selections=5,
)

This code allows you to select up to five local authorities which you can then use to filter the data. The example below (Figure 3) shows how it can be used in a bar chart.

Figure 3: A short GIF to illustrate how Streamlit multiple-option select boxes can enable one to filter data to be plotted in a bar chart.

Structuring the app

There are many ways to structure your app. Below, we give a couple of quick examples. Further options are illustrated in the Streamlit documentation here.

Expanders

You may want to add a way for users to expand or collapse certain content (see Figure 4). You can do this by using st.expander:

with st.expander("Click for IoD graphic:"):
iod_graphic = Image.open("path_to_image")
st.image(iod_graphic)
Figure 4: An illustration of how sections that expand or collapse content can be used to structure a Streamlit app.

Sidebars

You can also organise certain interactive elements of the app in a sidebar. In our example, we wanted to give users the option to change the colour palettes used in the maps and the IoD decile they were exploring (see Figure 5). To do this in your Streamlit app, you can add:

with st.sidebar:
#Add all the elements you want to be in the sidebar here.
Figure 5: An illustration of how single-select drop down boxes can be used in sidebars to enable further filtration of data.

Menu bar

If you want to add a lot of information and figures to your app, you may quickly find that pages become very long and crowded. One easy way to fix this is to use pages within your app (see Figure 6).

There are a few different ways to do this. In the example app we use the package ā€˜streamlit-option-menuā€™.

You can find more information about the package in its Github repository. After importing the pack, you can use sidebars to add new pages with bootstrap icons.

with st.sidebar:
choose = option_menu(
# Title of the navigation bar
"IoD Geographical Analysis",
# Title of the sections
["About", "English LA Breakdown",
"English LA Comparison", "English LSOA Breakdown"],
# Icons of the sections
icons=["house", "geo-alt","kanban", "geo-alt"],
#More style choices can be added in here, see the documentation for more details.
)
Figure 6: A GIF to illustrate how pages can be used to structure a Streamlit app.

Along with the example app Python file, we have created a second Python file in the Github repository with some of the basics explained in this tutorial. If you clone the Github repository, you will be able to use this file to test and trial different options. If you have read the previous blog in this series, you will be able to use the code described (as well as some code you have learnt here!) and recreate the example in a Streamlit app!

Streamlit also has its own way to create multi-page apps and add tabs within pages. We wonā€™t explore these in this blog but click the links if youā€™d like further details.

Adding a password to your app

If you are looking at sensitive data you may want to create a password for your app to restrict access. First, you will need to set up a secrets.toml file inside your .streamlit/ folder which holds the password for your app. See the Github repository for an example of a folder structure for your app.

PASSWORD='Nest@IoD'

Then in the main script, you can place all of the contents of the app you wish to be password protected inside a function:

def streamlit_iod():
# *contents of your app*

Then you can add a check at the end of the script to ensure you input the password correctly.

# This section provides password protection for the app.
pwd = st.sidebar.text_input("Password:", type="password")
# st.secrets reads it in from the toml folder, and then runs the streamlit_iod function if the password matches.
if pwd == st.secrets["PASSWORD"]:
streamlit_iod()
# To avoid the error message showing up on the first run, we have an if statement to check if the password is blank.
elif pwd == "":
pass
else:
st.sidebar.error("Password incorrect. Please try again.")

In our app we have put the password in the sidebar. If you want it in the main body of the app, you can use st.text_input(ā€œPassword:ā€, type=ā€passwordā€) instead. You can also look at the Streamlit documentation on passwords, which includes a more complex example.

When creating your own app, you will want to keep the secrets file on your local machine only as otherwise everyone would be able to see your password on the Github repository! We have published the app on Streamlit community cloud, which allows you to have a separate hidden secrets file to ensure password security.

How to change the theme of your app

To change the font or the colour scheme of your Streamlit app you could create a config.toml file inside your .streamlit/ folder and place all the theme considerations inside. This is what we used for the theme in our app:

[theme]
# Choosing the colour which outlines the widgets (i.e. the things in the selectors)
primaryColor="#F63366"
# Background colour of the app
backgroundColor="#FFFFFF"
# A secondary background colour (e.g. changes the colour of the sidebar)
secondaryBackgroundColor="#F0F2F6"
#Colour of the text
textColor="#262730"
# Change the font
font="sans serif"

See the Streamlit documentation here for more details.

Struggling with slow load times?

We have found that Streamlit apps can often be slow to load (especially when using geographical maps!). There are a couple of ways to speed this up. One simple way if you are loading in a lot of data is to use st.cache_data. You can add this at the top of any function that calls in a dataframe or other code involving loading data from a database. For example, calling APIā€™s. This (once run for the first time) then stores the data in cache. Therefore, as long as the parameters are the same when it is called again, instead of running it, it returns the cache instead!

@st.cache_data
def get_geo_data(suppress_st_warning=True):
#This returns a function which pulls in all the map data for Local Authorities (LA's) in England
geojson_la = "https://raw.githubusercontent.com/dap_medium_articles/dev/streamlit_app_tutorial/shapefiles/la_clean_shapefiles_2019.geojson"
geodata_la = alt.Data(
url=geojson_la, format=alt.DataFormat(property="features", type="json")
)
return geodata_la

There are other ways to speed up your app (as well as ways of clearing the cache) which can be found in the Streamlit documentation.

And there it is, your first Streamlit app!

Check out the Streamlit documentation if you want to learn more about how to create beautiful and interactive apps. It is filled with many great examples to get you started. And donā€™t forget to check out the example app we have been showcasing and the code used in the Github repository here!

--

--