Displaying text, data and metrics

Streamlit · Essentials · 10 min

Most apps are mainly displaying results, and choosing the right element makes them readable at a glance.

`st.write` is the Swiss Army knife: it accepts strings (rendered as Markdown), numbers, DataFrames, dicts, figures and more, and picks a suitable display. It also takes several arguments: st.write("Total:", total).

Magic: a bare expression on its own line, such as a variable name or a string, is written to the app automatically, as if wrapped in st.write. Handy for quick scripts; explicit calls are clearer in larger apps.

Dedicated elements give more control:

  • Text: st.title, st.header, st.subheader, st.markdown (with emoji shortcodes and colored text like :blue[text]), st.caption, st.code(src, language="python"), st.latex.
  • Data: st.dataframe(df) is an interactive grid with sorting, search and column resizing; column_config formats columns (currency, progress bars, links, images). st.table renders a static table. st.json shows a collapsible tree.
  • KPIs: st.metric("Revenue", "$12.3k", "+4.5%") shows a value with a colored delta.
  • Status: st.success, st.info, st.warning, st.error, st.exception, and st.toast for brief notifications.

st.dataframe handles large frames efficiently, but sending millions of rows to the browser is still slow; filter or aggregate first.

Anything displayed is part of the page only until the next rerun, when the script redraws everything from scratch.

Example

import pandas as pd
import streamlit as st

df = pd.DataFrame({"product": ["Tea", "Coffee", "Cocoa"],
                   "revenue": [1200.5, 3400.0, 560.25],
                   "share": [0.23, 0.66, 0.11]})

st.title("Sales overview")
st.markdown("Revenue for **March**, :blue[all regions].")

col1, col2 = st.columns(2)
col1.metric("Revenue", f"${df.revenue.sum():,.0f}", "+4.5%")
col2.metric("Products", len(df), "-1")

st.dataframe(df, hide_index=True, column_config={
    "revenue": st.column_config.NumberColumn("Revenue", format="$%.2f"),
    "share": st.column_config.ProgressColumn("Share", min_value=0, max_value=1),
})
st.write("Top product:", df.loc[df.revenue.idxmax(), "product"])
"Magic: this bare string is displayed too"
st.success("Data loaded")

Remember

  • st.write displays almost anything; bare expressions are shown via magic
  • st.dataframe with column_config gives interactive, formatted tables
  • st.metric shows KPIs with deltas; status elements show messages

Watch out for

  • Sending a multi-million-row DataFrame to st.dataframe instead of filtering or aggregating first.

Check yourself

  1. What does a line containing only a variable name, such as `df`, do in a Streamlit script?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: docs.streamlit.io/develop/api-reference/write-magic/st.write