FRESHLY BAKED: A Simple Guide for the Latest Version of Streamlit 1.18.0

xxxibdara
SFU Professional Computer Science
13 min readFeb 11, 2023

Authors: Jingyi Huang, Xiaoxiao Duan, Xiner Qian, Zeye Gu, Ziyao Cui

This blog is written and maintained by students in the Master of Science in Professional Computer Science Program at Simon Fraser University as part of their course credit. To learn more about this unique program, please visit {sfu.ca/computing/mpcs}.

Want to build a Web app? No front-end knowledge? Totally fine! This tutorial will give you a quick start on Streamlit's LATEST VERSION, a fast and straightforward method of building powerful data apps.

Fig. 1: Screenshot from: https://www.youtube.com/watch?v=Klqn--Mu2pE

Table of Contents:

1. Overview:

Let’s consider the following situations:

we might all have been through this: when we develop a project that needs a website to visualize our results, we would like to split the task into a visualization part and a data implementation part and assign them to different team members. Most of us are unlikely to do the back-end job and the front-end job simultaneously because they use totally different programming languages.

Fig. 2: Saved from https://www.springboard.com/blog/software-engineering/front-end-vs-back-end/

Therefore, it would be better if there is something that enables us to do those jobs together.

Meanwhile, what if a biology student wants to distribute the research findings? If a person with no knowledge of HTML, CSS, or Javascript wants to develop a web app, what should they do? Streamlit is here for you!

“All in pure Python. No front‑end experience required.”

1. 1 All about Python

Streamlit was built on Python in 2008, which is an open-source app framework for people and only uses Python scripts to quickly build interactive web apps. For example, machine learning engineers and data scientists could write scripts in a Jupyter notebook and directly use Python scripts to create apps. This is the most significant advantage of Streamlit: if you know Python, then you’re done.

Moving the code that generates these visualizations into a Streamlit dashboard is simple. Streamlit allows you to reuse any Python code you’ve already written. When compared to non-Python-based tools, this can save significant time. As a result, you can accelerate the iteration speed of your ML applications and create values with AI more quickly.

1.2 Python Libraries Compatible

More than that, another benefit of Streamlit is its compatibility with a range of major Python plotting libraries, with plans to support additional ones in the future. Currently, it supports Matplotlib’s Pyplot, Seaborn, Altair, Vega-Lite, Plotly, Bokeh, PyDeck (which includes 3D and mapping options), and GraphViz. This benefit provides the ability to create a variety of visualizations and dashboards using Streamlit.

Fig. 3: List of Compatible Libraries (Screenshot from streamlit.io)

This article will give you a step-by-step guide to creating some small dashboards to play with. And also, will point out the WHAT’s NEW in version 1.18.0 and some limitations we encounter in the progress.

2. Tutorial:

Streamlit is really easy to start prototyping with. You can get it up and running with just a few lines of code.

2.1 Get Started

Installing Streamlit is just as simple as installing other packages. Here are the steps to follow:

Step 1: Open your terminal or command prompt.

Step 2: Ensure you have met the prerequisites of Python 3.7+ and PIP.

Step 3: Run the following command to install Streamlit:

pip install streamlit 

And that’s it! With just one line, you’ve successfully installed Streamlit on your machine.

Big News: Boowww 🔥

Streamlit 1.18.0 is released. Today! As we are writing this post.

Fig. 4: Screenshot from https://docs.streamlit.io/library/changelog#version-1180

If you already have Strealit installed. To upgrade Streamlit, you can run:

pip install -upgrade streamlit

to check the version, run:

streamlit -version

Meanwhile, Streamlit shows us some beginner-friendly examples, which you can access by running the following command in your terminal or command prompt:

streamlit hello

Upon running the command, Streamlit will automatically open your browser and load a local webpage. You’ll find various demos you can explore on this page, along with the accompanying codes for each demo.

Fig. 5: the Mapping Demo Overview

After that, here is the command that runs the your_script.py file:

streamlit run your_script.py

2.2 Display Text and Graphs

2.2.1 Text:

After importing Streamlit, you can display text in various ways. The most common method is to explicitly use structure and pure text commands to customize the desired text.

import streamlit as st

# Structure
st.title("This is a title")
st.header("This is a header")
st.subheader("This is a subheader")
st.caption("This is a caption")

# Pure text
st.text("This is a text")
st.markdown("This is a markdown")

# Magic
st.write("This is a magic write")
Fig. 6: Result Based on the Above Example

However, Streamlit provides an easier way: Magic Write. With its help, you can simply write the content in your code files, and the st.write() function will automatically be invoked to display almost any common data science object you want, including markdown, numbers, DataFrames, and even charts.

# Markdown
'''
# This is a title
There are some markdowns
'''

# Numbers
1234

# DataFrame
import pandas as pd
df = pd.DataFrame({'A':[1,2], 'B':[3,4]})
df

# Chart
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.plot([1,2,3,4],[4,3,2,1])
fig
Fig. 7: ‘Magic Write’

2.2.2 Graph:

Streamlit has built-in support for several types of charts. You can use these functions to create and display these charts in your Streamlit app easily.

Bar Chart: st.bar_chart

In this example, we may be interested in approximately estimating how many restaurants are in each score and the percentage they represent. As a result, we processed the DataFrame grouping by the ‘stars’ attribute and ran the st.bar_chart() function to get the result shown below.

import streamlit as st
import pandas as pd

@st.cache_data
def load_data (path):
return pd.read_json(path, lines = True)

df = load_data ('./data/yelp_business.json')

bar_chart_data = df.groupby(['stars']).count()[['business_id']]
st.bar_chart(bar_chart_data)
Fig. 8: Bar Chart Example

Scatterplot on maps: st.map

Here we produced a scatter plot on maps, which shows the business locations in the select provinces.

import streamlit as st
import pandas as pd

@st.cache_data
def load_data (path):
return pd.read_json(path, lines = True)

file = './data/yelp_business.json'
map_data = load_data(file)

st.header("Scattorplot on map")

state_option = st.selectbox(
'Choose a state:',
('AB','MO','TN','CA','IN','ID','FL'))

filtered_data = map_data [map_data['state'] == state_option]
st.subheader (f'Bussiness in {state_option}:')
st.map(filtered_data)

def load_data_map():
data = load_data(file)
selected = data[['latitude', 'longitude', 'state']]
return selected

data_load_state = st.text ('Loading data...')
map_data = load_data_map ()
data_load_state.text('Loading data...done!')


st.map(map_data)
Fig. 9: Map Example

Table: st.table

We want to observe the restaurants’ opening hours at different times. This case is perfectly suited to be represented in a table. We directly extract the restaurant operating hours column and the operating hours of each restaurant on different days of the week, fill them into a new DataFrame created for days and hour times, and then obtain the desired result by calling st.table.

import streamlit as st
import pandas as pd
import re

# gain working hours data
@st.cache_data
def load_data (path):
return pd.read_json(path, lines = True)

df = load_data('./data/yelp_business.json')
workday = df['hours'].dropna()

# get time range from string
def time_range(string):
start, end = re.findall(r'\d+:\d+', string)
return (start, end)

# get end time with half hour ealier range
def get_end_time(time_str):
hour, minute = map(int, time_str.split(':'))
if minute >= 30:
minute = 0
else:
minute = 30
hour -= 1
if hour < 0:
hour = 23
return f"{hour}:{minute}"

# define table
days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
day_time_range = []
for i in range(24):
day_time_range.append(f"{i}:0")
day_time_range.append(f"{i}:30")

table_df = pd.DataFrame(columns=days, index=day_time_range)
table_df.fillna(0, inplace=True)

# fill records
@st.cache_data
def generate_table(table_df):
for record in workday:
for day in days:
try:
a,b=time_range(record[day])
if a=='0:0' and b=='0:0':
continue
else:
table_df.loc[a:get_end_time(b),day]+=1
except:
continue
return table_df

st.table(generate_table(table_df))
Fig. 10: Table from the Above Example

2.3 Interact with Other Visualization Libraries

While Streamlit’s built-in chart components are easy to generate, they are limited in terms of input data, height, and width. If you’re looking for more customizable and visually appealing charts, similar to those offered by pyplot, Plotly, PyDeck, or Graphviz, Streamlit also provides support for these libraries.

By leveraging popular libraries such as Plotly, you can use Streamlit as a platform to showcase your data insights in a visually appealing and user-friendly way.

In this demonstration, we take a look at how Streamlit can be used in conjunction with Plotly to create stunning sunburst charts. The code provided allows users to select the categories they want to include in the chart, and Plotly’s sunburst visualization is then used to display the data in a highly interactive and informative way. This example showcases the versatility of Streamlit and its ability to work seamlessly with other popular data visualization libraries.

Plotly: st.plotly_chart

import pandas as pd
import streamlit as st
import plotly.express as px


@st.cache_data
def load_data(path):
return pd.read_json(path, lines= True)

def sun_burst(df):
categories = ('city', 'state', 'stars', 'review_count', 'is_open')
st.subheader('Sunburst Chart')

selected_categories = st.multiselect('Select categories to include in sunburst chart', categories)

if selected_categories:
fig = px.sunburst(data_frame = df, path=selected_categories)
st.plotly_chart(fig)
else:
st.write("No categories selected")

df = load_data('./data/yelp_business.json')
df = df.dropna(subset=['categories'])
sun_burst(df)
Fig. 11: Sunburst Chart Example

The column ‘stars’ is in the range from 0.0 to 5.0 which represents the rating of a business, and the ‘is_open’ can be either 1 or 0 which indicates whether a business is open or closed.

When you hover your mouse on any area in the chart. Detailed information will be provided. In this case, when you hover your mouse on the red area which indicates stars equals 3.5 and is_open equals 1, the number of businesses in this area will be shown which is 1314.

Fig. 12: Search Bar
Fig. 13: Sunburst Chart Demonstration

Users can select desired properties from a dropdown menu in the search bar or type to narrow options. This allows for more flexible and efficient searches.

2.4 User Interface

As mentioned above, when showing graphs, if that’s only for display, then Streamlit is nothing more than that. The strength of Streamlit is that it makes it easy for people who don’t know how to write a front-end to build the interactive interface they need, as well as a comfortable and convenient layout.

2.4.1 Input widgets

In fact, almost every interaction component you find on the website or in the application can be easily implemented on Streamlit. Here are a few examples of buttons, selectors, and sliders. More examples can be found in the Streamlit document. They are as simple as the presented widgets, requiring only one line of coding.

import streamlit as st
import pandas as pd

file = 'yelp_business.json'
df = pd.read_json(file, lines = True)
df
# Button
st.button("Click me")
with open(file) as f:
st.download_button("Download dataset", f, 'data.json')

# Selector
st.checkbox("is_open")
st.radio("Select one", ['0','1'])
st.selectbox("Select one", ['0','1'])
st.multiselect("Select one", ['0','1'])
# Slider
st.slider("Select star", 0, 5)
st.select_slider("Select star", ["Poor", "Fair", "Average", "Good", "Excellent"])
Fig. 14: Input Widgets

2.4.2 Display component

In addition to those various components for input, Streamlit is not just about text and graphs when it comes to displaying. If you want to play multimedia on the page, you can use st.image(), st.audio(), and st.video() to show your content.

When you have a lot of content to display with different focuses, a multipage application is required. Trying to put them on a separate page and having a clear navigation bar can improve the readability of your results. In Streamlit, this is achieved by simply adding a “pages” folder to your working directory and putting other subpages in the new “pages” folder.

Here, a wise file name can lead to more clear navigation on your homepage. The file name will automatically become the label on the navigation bar. The symbol “-” will help you easily name your file. And the number in the front of the file name will become the navigation order.

Now your directory should look like this:

your_working_directory
├─ streamlit_app.py ← Your main script
└─ pages
├── 1_page.py ← first page
└── 2_page.py ← second page

For example in Fig. 15:

Fig. 15: Work Directory
Fig. 16: Multipage Demonstration

You may notice something displayed on the sidebar. This is easily accomplished by inserting a “sidebar” between the first and last name. You can compare this code to the above one.

file = './data/yelp_business.json'
st.sidebar.write("You can download the dataset we used here:")
with open(file) as f:
st.sidebar.download_button("Download dataset", f, 'data.json')

2.5 Deploy

Now, you should follow our steps to successfully build a Streamlit app, no matter if it is our demo or your own work. Of course, the app is only accessible locally right now. It’s not practical to expect others to run your code themselves to see your results. The good news is, Streamlit also provides an extremely easy way to deploy your app. Once you log in to Streamlit Cloud, you just need to follow the instructions to create a new app and paste your GitHub link, and you can successfully build your own website in a few seconds! Check Fig. 17.

Fig. 17: Deploy Your App

3. Performances

During the development, when you change the source code you can see a list of buttons at the top right corner of the app in Fig. 18. If you click the ‘Always rerun’ button the app can automatically re-execute every time you change your source code. This functionality improves developers’ work efficiency.

Fig. 18: Execution Button Screenshot from the App

When the app re-executes itself, all the code in the app will be re-executed which leads to a serious problem. If you have loaded a large dataset locally, every time you modify the code, the Strealit app takes a long time to reload. It severely impacts programmers’ development efficiency.

3.1 New Version Highlights

3.1.1 st.cache_data

In Strealit version 1.18.0 which was released on February 09, 2023, ‘st.chache_data’ and ‘st.cache_resource’ are two new function decorators that solve the issue that was mentioned previously. The st.chache_data decorator caches the output of functions with the same argument. It is useful when the function is computationally expensive, and you need to use the output multiple times. There are some use cases where st.cache_data can be useful such as loading large datasets, pre-processing data, training machine learning models, and complicated visualizations, etc.

There are three requirements that st.cache_data needs to check.

  1. The name of the function
  2. The code of the function body
  3. The input parameter when you call the function

When it is the first time that Streamlit sees a new combination of the function name, function body, and parameter(s), it will execute the function for the first time and store a copy of the output along with the function name and parameter(s) in the cache. When Streamlit encounters the same combination without changing the three requirements mentioned above, the function will not actually execute again but instead return the previously stored result from the cache.

import streamlit as st
import time


@st.cache_data
def slow_function(arg):
time.sleep(10) # Simulating a slow operation
return arg


def main ():
result = slow_function(42)
st.write("Result:", result)


# This will return the cached result immediately, without executing the function again
result = slow_function(42)
st.write("Result:", result)
Fig. 19: Streamlit Cache Demonstration

In the above code, the function load_data is decorated with @st.cache_data. Although slow_function is called twice in this case it only executes once. Using st.cache_data can be a useful optimization technique when working with time-consuming functions in Streamlit.

When a developer modifies the code in the example above, for example by adding a print statement, during the rerun of the Streamlit app, the slow_function() will not run even once, because the return object of it already exists in the cache from the first run, since the developer did not change any code related to the slow_function. This case solves the issue of the efficiency of development being affected by the repeated loading of large datasets mentioned previously.

3.1.2 st.cache_resource

Now, let’s talk about the other changes in caching. Compared with st.cache_data, the following graph shows us the main differences between them. For example, st.cache_data focuses on "data", which means it can cache anything that can be stored in a database. Otherwise, please use st.cache_resource.

Previously, st.cache imposed some restrictions on Streamlit, such as slow execution and the need to load objects multiple times after changing the code. But st.cache_resource improves those behaviors! It is recommended to cache global resources, like ML models or database connections.

Fig. 20: Saved from streamlit.io/library/advanced-features/caching

There are a few things we should keep in mind when using st.cache_resource:

  1. It does not store a copy of the object, instead, it directly stores the object itself in the cache, therefore, if we make a change to it, it will affect the object. Making sure the final result is thread-safe becomes important.
  2. Return values of functions do not need to be serializable. For example, database connections are not serializable by nature, therefore it is not possible to be cached by st.cache_data.

3.2 Limitations:

  • Limited styling options: Streamlit has limited options for customizing the look of your application, making it harder to create a unique look.
  • Limited chart customization: Streamlit itself doesn’t have as much support for advanced functionality and customization, but if applied with other libraries can have more complex applications.
  • Performance: Streamlit may not perform well for larger, more complicated applications, resulting in sluggish loading and rendering. Small to medium-sized datasets are better suited for Streamlit, which reduces the likelihood that the app would operate slowly or even crash.

Despite these limitations, Streamlit is still a popular choice among data scientists and machine learning practitioners due to its simplicity and ease of use for prototyping and deploying models.

4. Conclusion:

Streamlit is a great choice for building interactive, web-based applications for data science and machine learning. It’s easy to set up and use, but there are some limitations to keep in mind.

Thank you for reading.

Fig. 21: Saved from: /thanks-for-reading/

References:

1. https://docs.streamlit.io/library/advanced-features/caching

--

--