Exercises: Streamlit Dashboards
Install: pip install streamlit pandas plotly. Run apps with streamlit run app.py from the terminal, not from Jupyter.
Part A: Conceptual (6 problems)
A.1 ★☆☆ | Recall
Describe Streamlit's execution model in one sentence.
Guidance
A Streamlit app is a Python script that re-runs from top to bottom on every user interaction.A.2 ★☆☆ | Recall
What is the difference between @st.cache_data and @st.cache_resource?
Guidance
`cache_data` is for serializable data (DataFrames, lists, dicts). It deep-copies the result, making it safe for later mutation. `cache_resource` is for non-serializable objects (database connections, ML models). It returns the same object reference, which is necessary for connection pools and stateful objects.A.3 ★★☆ | Understand
Why does Streamlit need caching, and what happens without it?
Guidance
Without caching, every widget interaction re-runs the entire script including expensive operations (data loading, model training, API calls). The app becomes unresponsive. Caching stores the output of expensive functions and returns the cached value on subsequent calls with the same arguments, so only the cheap code runs on each interaction.A.4 ★★☆ | Understand
When should you use st.session_state instead of a local variable?
Guidance
Local variables reset on every re-run. `session_state` persists across re-runs for the user's session. Use session_state for: counters, multi-step workflows, persistent selections, form values, and anything that needs to survive across widget interactions.A.5 ★★★ | Analyze
The chapter's threshold concept is "apps are scripts." How is this different from a traditional web framework like Flask?
Guidance
Flask has event handlers, routes, and component lifecycles. You write `@app.route("/path")` for a URL handler, `@app.before_request` for setup, etc. Streamlit has none of these. It is a plain Python script that re-runs top-to-bottom. The benefit is massively lower cognitive overhead; the cost is that complex interactivity (cross-filtering, real-time updates) is harder than in callback-based frameworks like Dash.A.6 ★★★ | Evaluate
When should you choose Dash over Streamlit for a project?
Guidance
Choose Dash when: (1) you need cross-filtering between multiple charts, (2) you have many interactive controls with complex dependencies, (3) you need custom CSS styling beyond Streamlit's theme system, (4) the app has high concurrency requirements and you need enterprise scaling. Streamlit is faster to build and easier to learn, so default to Streamlit unless these specific needs arise.Part B: Applied (10 problems)
B.1 ★☆☆ | Apply
Create a minimal Streamlit app that displays a title and a DataFrame.
Guidance
# app.py
import streamlit as st
import pandas as pd
st.title("My App")
df = pd.DataFrame({"a": [1, 2, 3], "b": [4, 5, 6]})
st.dataframe(df)
Run with `streamlit run app.py`.
B.2 ★☆☆ | Apply
Add a sidebar with a slider controlling the number of rows shown.
Guidance
n = st.sidebar.slider("Rows", 1, 100, 10)
st.dataframe(df.head(n))
B.3 ★★☆ | Apply
Add caching to a data-loading function with @st.cache_data.
Guidance
@st.cache_data
def load_data():
return pd.read_csv("data.csv")
df = load_data()
B.4 ★★☆ | Apply
Create a three-column layout with KPI metrics.
Guidance
col1, col2, col3 = st.columns(3)
col1.metric("Revenue", "$1.2M", "+15%")
col2.metric("Users", "45,678", "+7%")
col3.metric("Conversion", "3.4%", "-0.2%")
B.5 ★★☆ | Apply
Embed a Plotly chart that updates based on a selectbox.
Guidance
import plotly.express as px
col = st.selectbox("Column", df.columns)
fig = px.histogram(df, x=col)
st.plotly_chart(fig, use_container_width=True)
B.6 ★★☆ | Apply
Create a multi-tab layout with three tabs: Overview, Details, Raw Data.
Guidance
tab1, tab2, tab3 = st.tabs(["Overview", "Details", "Raw Data"])
with tab1:
st.write("Summary")
with tab2:
st.write("Details")
with tab3:
st.dataframe(df)
B.7 ★★★ | Apply
Use st.session_state to build a counter that increments on button click.
Guidance
if "count" not in st.session_state:
st.session_state.count = 0
if st.button("Increment"):
st.session_state.count += 1
st.write(f"Count: {st.session_state.count}")
B.8 ★★☆ | Apply
Add a st.download_button to export a filtered DataFrame as CSV.
Guidance
st.download_button(
"Download CSV",
filtered.to_csv(index=False),
file_name="data.csv",
mime="text/csv",
)
B.9 ★★☆ | Apply
Use st.form to batch several widgets with a submit button.
Guidance
with st.form("my_form"):
name = st.text_input("Name")
age = st.number_input("Age", 0, 120)
submitted = st.form_submit_button("Submit")
if submitted:
st.write(f"Hello, {name} ({age})")
B.10 ★★★ | Create
Build a complete climate dashboard with sidebar filters (date range, variable selection), a Plotly line chart, KPI metrics, and a download button.
Guidance
Use the progressive-project skeleton from Section 29.12 of the chapter. About 80 lines of Python, producing a full dashboard with data loading, filtering, charting, metrics, and export.Part C: Synthesis (4 problems)
C.1 ★★★ | Analyze
You have a dashboard that re-runs 30 seconds on every interaction. Profile it and determine which part is slow, then apply caching.
Guidance
Use `%time` or `time.time()` around each major step. Typically the culprit is data loading or an expensive transformation. Wrap the slow function with `@st.cache_data` (or `@st.cache_resource` if it produces an unserializable object). Verify that subsequent interactions are fast.C.2 ★★★ | Evaluate
A colleague has built a Streamlit app with all its data loading at the top of the script without caching. The app takes 45 seconds per interaction. What is your fix?
Guidance
Wrap the data loading in a `@st.cache_data`-decorated function. This alone usually solves the problem. If the data is truly too large to cache, consider pre-aggregating before loading or using a smaller subset for the dashboard.C.3 ★★★ | Create
Deploy a Streamlit app to Streamlit Community Cloud. Document the steps in a README.md.
Guidance
Steps: (1) create a GitHub repo with `app.py` and `requirements.txt`; (2) go to share.streamlit.io; (3) click "New app" and connect the repo; (4) specify the main file; (5) wait for build; (6) share the URL. Document each step with screenshots for the README.C.4 ★★★ | Evaluate
Streamlit's re-run model is both a strength and a limitation. Discuss when it helps and when it hurts.
Guidance
**Helps**: gentle learning curve (no callbacks to understand), linear code (top-to-bottom mental model), good for exploration (change something, see the result). **Hurts**: every interaction re-runs everything (slow without caching), stateful apps are awkward (session_state everywhere), complex dependencies are implicit (hard to see which widget affects which chart). For simple dashboards, the help outweighs the hurt. For complex dashboards, Dash's explicit callbacks become the better choice.Chapter 30 introduces Dash, the main alternative to Streamlit with a different execution model.