Python Streamlit Dashboards 2026-07-20 9 min

Streamlit for Data Analysts: Build Interactive Dashboards in Pure Python

Streamlit turns Python scripts into shareable web apps in minutes — no HTML, CSS, or JavaScript required. For data analysts, it's the fastest way to move from a Jupyter notebook to a live, interactive dashboard that stakeholders can actually use.

Isachenko Andrii
Isachenko Andrii
Data Analyst · Open to work

📋 Table of Contents

  1. Why Streamlit for Analysts
  2. Setup and First App in 5 Minutes
  3. KPI Dashboard: Metrics, Charts, Filters
  4. Working with Real Data: SQL + Pandas
  5. Adding AI: Chat with Your Data
  6. Deploying to Streamlit Cloud
  7. Streamlit vs Power BI vs Tableau

Why Streamlit for Analysts

Power BI and Tableau are excellent BI tools, but they have a hard ceiling: if your stakeholder wants something that Power BI can't do — custom ML predictions, dynamic SQL queries, API integrations — you're stuck. Streamlit removes that ceiling. If you can write it in Python, you can put it in a Streamlit app.

The key insight is that Streamlit re-runs your entire script top to bottom whenever a user interacts with a widget. This sounds inefficient but is actually elegant — your app logic stays in pure Python, with no callback hell, no state management boilerplate, and no JavaScript.

Streamlit is not a replacement for Power BI or Tableau — it's what you reach for when your analysis needs to become a product: a live tool that non-analysts can interact with, not just a static report they read once.

Setup and First App in 5 Minutes

pip install streamlit pandas plotly

# Create app.py:
import streamlit as st
import pandas as pd
import plotly.express as px

st.title("My First Data App")
st.write("Upload a CSV to explore your data.")

uploaded = st.file_uploader("Choose a CSV file", type="csv")
if uploaded:
    df = pd.read_csv(uploaded)
    st.dataframe(df.head(20))
    st.write(f"Shape: {df.shape[0]} rows × {df.shape[1]} columns")

# Run with:
# streamlit run app.py

That's a fully functional file explorer in 12 lines of Python. Streamlit handles the HTTP server, file upload UI, and data rendering automatically.

KPI Dashboard: Metrics, Charts, Filters

Here's a realistic KPI dashboard structure for an e-commerce analyst:

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

st.set_page_config(page_title="Sales Dashboard", layout="wide")

@st.cache_data  # Cache data loading for performance
def load_data():
    return pd.read_csv("sales.csv", parse_dates=["date"])

df = load_data()

# ── Sidebar filters ──
st.sidebar.header("Filters")
date_range = st.sidebar.date_input(
    "Date range",
    value=(df["date"].min(), df["date"].max())
)
categories = st.sidebar.multiselect(
    "Category",
    options=df["category"].unique(),
    default=df["category"].unique()
)

# Apply filters
mask = (
    (df["date"] >= pd.Timestamp(date_range[0])) &
    (df["date"] <= pd.Timestamp(date_range[1])) &
    (df["category"].isin(categories))
)
filtered = df[mask]

# ── KPI metrics row ──
col1, col2, col3, col4 = st.columns(4)
col1.metric("Total Revenue",   f"${filtered['revenue'].sum():,.0f}",   "+12%")
col2.metric("Orders",          f"{filtered['orders'].sum():,}",         "+8%")
col3.metric("Avg Order Value", f"${filtered['revenue'].mean():,.2f}",  "+3%")
col4.metric("Customers",       f"{filtered['customer_id'].nunique():,}", "+5%")

# ── Charts ──
st.subheader("Revenue Trend")
daily = filtered.groupby("date")["revenue"].sum().reset_index()
fig = px.line(daily, x="date", y="revenue", title="Daily Revenue")
st.plotly_chart(fig, use_container_width=True)

st.subheader("Top Categories")
cat_rev = filtered.groupby("category")["revenue"].sum().sort_values(ascending=True)
fig2 = px.bar(cat_rev, orientation="h")
st.plotly_chart(fig2, use_container_width=True)
✅ Always use @st.cache_data for data loading functions. Without it, Streamlit reloads the CSV on every user interaction, which kills performance for large datasets.

Working with Real Data: SQL + Pandas

Streamlit integrates natively with SQLAlchemy, which means you can connect directly to PostgreSQL, BigQuery, or any other database your team uses:

import streamlit as st
import pandas as pd
from sqlalchemy import create_engine, text

# Store credentials in .streamlit/secrets.toml (never in code)
engine = create_engine(st.secrets["database"]["url"])

@st.cache_data(ttl=3600)  # Refresh cache every hour
def run_query(sql: str) -> pd.DataFrame:
    with engine.connect() as conn:
        return pd.read_sql(text(sql), conn)

# Dynamic SQL based on user input
metric = st.selectbox("Metric", ["revenue", "orders", "customers"])
period = st.radio("Group by", ["day", "week", "month"])

query = f"""
    SELECT
        DATE_TRUNC('{period}', order_date) AS period,
        SUM({metric})                      AS value
    FROM orders
    WHERE order_date >= CURRENT_DATE - INTERVAL '90 days'
    GROUP BY 1
    ORDER BY 1
"""

df = run_query(query)
st.line_chart(df.set_index("period")["value"])

Adding AI: Chat with Your Data

Streamlit 1.30+ includes st.chat_message and st.chat_input components that make it trivial to add LLM-powered chat to any data app:

import streamlit as st
import openai

client = openai.OpenAI(api_key=st.secrets["openai"]["api_key"])

if "messages" not in st.session_state:
    st.session_state.messages = []

# Display chat history
for msg in st.session_state.messages:
    with st.chat_message(msg["role"]):
        st.write(msg["content"])

# User input
if prompt := st.chat_input("Ask about your data..."):
    st.session_state.messages.append({"role": "user", "content": prompt})
    with st.chat_message("user"):
        st.write(prompt)

    # System context includes data summary
    system = f"""You are a data analyst assistant.
    The dataset has {len(df)} rows and columns: {', '.join(df.columns)}.
    Summary statistics: {df.describe().to_string()}"""

    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[{"role": "system", "content": system}] +
                  st.session_state.messages
    )
    answer = response.choices[0].message.content

    st.session_state.messages.append({"role": "assistant", "content": answer})
    with st.chat_message("assistant"):
        st.write(answer)

Deploying to Streamlit Cloud

Streamlit Cloud offers free hosting for public GitHub repositories. Deployment takes 3 steps:

  1. Push your app.py and requirements.txt to GitHub
  2. Go to share.streamlit.io → New app → select your repo
  3. Add secrets (database URLs, API keys) in the Secrets panel

Your app is live at yourusername-appname.streamlit.app in under 2 minutes. For private data, use Streamlit Community Cloud with private repos, or self-host on a VPS with Docker.

Streamlit vs Power BI vs Tableau

CriteriaStreamlitPower BITableau
Learning curveLow (Python)Medium (DAX)Medium (VizQL)
Custom logicUnlimited (Python)Limited (DAX)Limited (calculated fields)
ML integrationNativeVia Python/R visualVia TabPy
CollaborationGit-basedPower BI ServiceTableau Server/Cloud
CostFree (Cloud free tier)$10–20/user/month$35–70/user/month
Best forCustom data appsCorporate BIData storytelling
⚠️ Streamlit is not designed for highly formatted pixel-perfect reports. If your stakeholder needs a polished PDF-style report, Power BI paginated reports or a Jupyter notebook export is better suited.
Tags: Streamlit Python Dashboard Plotly Data App