DevelopmentFebruary 05, 20255 min read

Data Dashboard with Pandas and Streamlit

Build an interactive data dashboard with Pandas and Streamlit — filters, charts, and KPI cards that update live from any CSV.

Galvan

Galvan

Founder & Creator

Introduction

Data is everywhere — spreadsheets, CSV exports, survey results, sales records, and API responses. The ability to quickly explore, filter, and visualise a dataset is one of the most valuable skills a developer or analyst can have.

In this tutorial you will build a fully interactive Data Dashboard using Pandas and Streamlit. Users can upload any CSV file and immediately get column statistics, apply filters, sort data, and view bar charts, line charts, and scatter plots — all without writing a single line of code after the app is deployed.

This project pairs well with the File Organizer tutorial for working with local files, and with Sentiment Analysis for exploring text data.


What You Will Build

  • CSV Upload — drag-and-drop any CSV file
  • Data Preview — first N rows with column types
  • Summary Statistics — count, mean, min, max, std for numeric columns
  • Column Filter — select which columns to display
  • Value Filter — filter rows by any column value
  • Sorting — sort by any column, ascending or descending
  • Charts — bar, line, and scatter plots
  • Download — export the filtered dataset as a new CSV

  • Prerequisites

  • Python 3.8+python.org
  • Libraries:
  • code
    pip install streamlit pandas
    PackageVersionPurpose
    streamlit≥ 1.32Web app framework
    pandas≥ 2.0Data loading, filtering, aggregation
    iobuilt-inIn-memory CSV export

    Step 1: Page Setup and File Upload

    Create dashboard.py:

    code
    import io
    import pandas as pd
    import streamlit as st
    
    st.set_page_config(
        page_title="Data Dashboard",
        page_icon="📊",
        layout="wide"
    )
    
    st.title("📊 Interactive Data Dashboard")
    st.write("Upload a CSV file to explore, filter, and visualise your data instantly.")
    
    uploaded_file = st.file_uploader(
        "Choose a CSV file",
        type=["csv"],
        help="The file should have a header row. Max recommended size: 50 MB."
    )

    Step 2: Load and Cache the Data

    Use st.cache_data to avoid reloading the file on every Streamlit rerun:

    code
    @st.cache_data
    def load_data(file) -> pd.DataFrame:
        return pd.read_csv(file)
    
    if uploaded_file is not None:
        df = load_data(uploaded_file)
        st.success(f"✅ Loaded **{len(df):,} rows** and **{len(df.columns)} columns**")
    else:
        st.info("👆 Upload a CSV file above to get started.")
        st.stop()

    st.cache_data stores the parsed DataFrame in memory. The function only runs again if the uploaded file changes, which keeps the app snappy even for large files.


    Step 3: Data Overview

    Show the shape, column types, and a configurable number of preview rows:

    code
    with st.expander("🔍 Data Overview", expanded=True):
        col1, col2, col3 = st.columns(3)
        col1.metric("Rows", f"{len(df):,}")
        col2.metric("Columns", len(df.columns))
        col3.metric("Missing Values", int(df.isnull().sum().sum()))
    
        preview_rows = st.slider("Rows to preview", 5, 50, 10)
        st.dataframe(df.head(preview_rows), use_container_width=True)
    
        st.write("**Column Types:**")
        col_types = pd.DataFrame({
            "Column": df.columns,
            "Type": df.dtypes.astype(str).values,
            "Non-Null Count": df.notnull().sum().values,
            "Null Count": df.isnull().sum().values,
        })
        st.dataframe(col_types, use_container_width=True, hide_index=True)

    Step 4: Summary Statistics

    code
    with st.expander("📈 Summary Statistics"):
        numeric_cols = df.select_dtypes(include="number").columns.tolist()
        if numeric_cols:
            st.dataframe(
                df[numeric_cols].describe().round(2),
                use_container_width=True
            )
        else:
            st.info("No numeric columns found in this dataset.")

    df.describe() returns count, mean, std, min, 25th/50th/75th percentile, and max for every numeric column — a one-liner that saves hours of manual calculation.


    Step 5: Column and Value Filters

    Let users narrow down the data using the sidebar:

    code
    st.sidebar.header("🔧 Filters")
    
    # Column selector
    all_cols = df.columns.tolist()
    selected_cols = st.sidebar.multiselect(
        "Show columns:", all_cols, default=all_cols[:min(6, len(all_cols))]
    )
    
    # Value filter for categorical columns
    cat_cols = df.select_dtypes(include="object").columns.tolist()
    filtered_df = df.copy()
    
    for col in cat_cols[:3]:  # limit to first 3 categorical columns
        unique_vals = df[col].dropna().unique().tolist()
        if len(unique_vals) <= 30:  # only show filter for low-cardinality columns
            chosen = st.sidebar.multiselect(
                f"Filter by {col}:", unique_vals, default=unique_vals
            )
            filtered_df = filtered_df[filtered_df[col].isin(chosen)]
    
    # Numeric range filters
    for col in df.select_dtypes(include="number").columns[:2]:
        min_val = float(df[col].min())
        max_val = float(df[col].max())
        chosen_range = st.sidebar.slider(
            f"{col} range:",
            min_value=min_val,
            max_value=max_val,
            value=(min_val, max_val)
        )
        filtered_df = filtered_df[
            filtered_df[col].between(chosen_range[0], chosen_range[1])
        ]

    Step 6: Sortable Filtered Table

    code
    st.subheader("📋 Filtered Data")
    
    col_sort, col_order = st.columns(2)
    with col_sort:
        sort_by = st.selectbox("Sort by:", selected_cols)
    with col_order:
        ascending = st.radio("Order:", ["Ascending", "Descending"]) == "Ascending"
    
    display_df = (
        filtered_df[selected_cols]
        .sort_values(by=sort_by, ascending=ascending)
        .reset_index(drop=True)
    )
    
    st.info(f"Showing **{len(display_df):,}** of **{len(df):,}** rows")
    st.dataframe(display_df, use_container_width=True)

    Step 7: Charts

    Provide three chart types — bar, line, and scatter:

    code
    st.divider()
    st.subheader("📊 Visualisations")
    
    numeric_cols = filtered_df.select_dtypes(include="number").columns.tolist()
    all_cols_list = filtered_df.columns.tolist()
    
    if not numeric_cols:
        st.warning("No numeric columns available for charting.")
    else:
        chart_type = st.radio(
            "Chart Type:", ["Bar Chart", "Line Chart", "Scatter Plot"],
            horizontal=True
        )
    
        if chart_type in ["Bar Chart", "Line Chart"]:
            x_col = st.selectbox("X axis:", all_cols_list, key="x")
            y_col = st.selectbox("Y axis:", numeric_cols, key="y")
            chart_data = filtered_df[[x_col, y_col]].dropna()
            if chart_type == "Bar Chart":
                st.bar_chart(chart_data.set_index(x_col))
            else:
                st.line_chart(chart_data.set_index(x_col))
    
        elif chart_type == "Scatter Plot":
            x_col = st.selectbox("X axis:", numeric_cols, key="sx")
            y_col = st.selectbox("Y axis:", numeric_cols, key="sy")
            st.scatter_chart(
                filtered_df[[x_col, y_col]].dropna(),
                x=x_col, y=y_col
            )

    Step 8: Download Filtered Data

    code
    st.divider()
    st.subheader("⬇️ Export")
    
    buffer = io.StringIO()
    display_df.to_csv(buffer, index=False)
    st.download_button(
        label="⬇️ Download Filtered CSV",
        data=buffer.getvalue(),
        file_name="filtered_data.csv",
        mime="text/csv",
        use_container_width=True,
    )

    Run the App

    code
    streamlit run dashboard.py

    Pandas Cheat Sheet for This Project

    TaskPandas Code
    Load CSVpd.read_csv("file.csv")
    First N rowsdf.head(N)
    Column data typesdf.dtypes
    Count missing valuesdf.isnull().sum()
    Select numeric columnsdf.select_dtypes(include="number")
    Filter rows by valuedf[df["col"] == value]
    Filter rows by rangedf[df["col"].between(a, b)]
    Sort rowsdf.sort_values(by="col", ascending=True)
    Summary statisticsdf.describe()
    Select columnsdf[["col1", "col2"]]
    Reset indexdf.reset_index(drop=True)
    Export to CSV stringdf.to_csv(index=False)

    Streamlit Data Display Components

    ComponentBest For
    st.dataframe()Interactive, sortable, resizable table
    st.table()Static, read-only table
    st.bar_chart()Quick bar charts from a DataFrame
    st.line_chart()Time series and trend lines
    st.scatter_chart()Correlation and distribution plots
    st.metric()Single KPI numbers with delta
    st.json()Display raw JSON data

    Handling Common CSV Issues

    ProblemFix
    Wrong encodingpd.read_csv(file, encoding="latin-1")
    Semicolon delimiterpd.read_csv(file, sep=";")
    No header rowpd.read_csv(file, header=None)
    Mixed numeric/text in a columnpd.to_numeric(df["col"], errors="coerce")
    Date columns read as stringspd.to_datetime(df["date_col"])
    Memory error on large filepd.read_csv(file, chunksize=10000)

    What to Try Next

  • Add correlation heatmap using st.pyplot() with seaborn.heatmap(df.corr()).
  • Support Excel files (.xlsx) by adding openpyxl and using pd.read_excel().
  • Add group-by aggregation — group by a categorical column and show mean/sum per group.
  • Show outlier detection — flag rows where any numeric value is more than 3 standard deviations from the mean.
  • Cache results to SQLite using the built-in sqlite3 module.

  • Sentiment Analysis App — Another data-focused Streamlit app, this time analysing the polarity of text rather than numeric data.
  • File Organizer — Uses Python's pathlib and shutil to work with files on disk, a great complement to CSV-based data work.
  • Recipe Finder — Shows how to work with structured JSON data from an API, similar to working with tabular CSV data.

  • Conclusion

    You have built a fully featured interactive data dashboard in Python using Pandas and Streamlit. The app handles CSV uploads, shows summary statistics, provides multi-column filtering, supports three chart types, and exports the filtered result — all with minimal code and zero frontend experience required.

    Pandas and Streamlit together are one of the most productive combinations in the Python ecosystem for rapid data exploration and sharing.

    Resources:

  • Pandas Documentation
  • Pandas Cheat Sheet (PDF)
  • Streamlit Charts Documentation
  • Streamlit st.cache_data
  • Streamlit st.dataframe