Interactive Visualization
Let the audience ask their own questions — safely
Interaction earns its place when it serves exploration or drilldown, not decoration: altair/plotly/streamlit let stakeholders filter, hover and trace their own questions while the analyst keeps the data honest.
What you will learn
- Choose an interaction tool per need
- Build filter/hover/drilldown interactions
- Ship an interactive app without leaking the data layer's secrets
What is this?
Interactive visualization layers filters, hovers, tooltips and traces on static grammar: Plotly (rich JS charts), Altair (declarative Vega-Lite), and Streamlit (turn scripts into apps). Interaction is powerful when it lets users explore soundly — filtering well-defined segments — and corrosive when it hides definitions or encourages cherry-picked claims.
Why do you need it?
- Self-service filtering moves the analytical conversation from 'can you slice?' to the decision.
- Hover-loaded tooltips put definitions at the point of confusion.
- Plotly/Altair ship from notebooks to the web without an app dev team.
- Constrained exploration (segment filters, honest axes) keeps interaction structured.
Mental model
A museum exhibit with labeled drawers visitors may open
Interactive visualization
The drawers are labelled and the exhibit stays truthful — visitors explore behind glass until they reach the panels they can open under rules. Interactive charts are the same: structured, labeled, explorable, never a blank unmarked vault.
How it works
- plotly.express/plotly.graph_objects render hoverable, zoomable charts from DataFrames.
- Altair specifies charts declaratively with selection binding to filters.
- Streamlit wraps a script: sliders/multiselects re-filter and re-draw live.
- Widgets bind to chart 'selection' in Altair; callbacks re-render in Plotly Dash.
- Keep the data layer separate: summary grains and pre-written filters, not raw secrets.
- Ship with a refresh cadence and honest naming of the source grain.
Static → interactive pipeline.
Examples
A 10-line interactive board
import pandas as pdimport plotly.express as px df = pd.DataFrame({"region": ["US"] * 4 + ["EU"] * 4, "q": ["Q1","Q2","Q3","Q4"] * 2, "revenue": [10, 12, 13, 15, 8, 9, 9, 11]})fig = px.line(df, x="q", y="revenue", color="region", markers=True, title="Revenue by quarter (hover for exact values)")fig.write_html("interactive.html")print("interactive.html: hover + legend filtering built in")Plotly Express yields hover, zoom and legend-toggle interactivity from one DataFrame — exploration without rebuilding.
In production
- A growth team ships a Streamlit funnel explorer with fixed segment definitions.
- A support ops board offers hover tooltips showing response-time definitions inline.
- An experimentation desk publishes a Plotly lift explorer where users toggle variants on fixed axes.
Best practices
- Gate interactions to well-defined segments so exploration stays sound.
- Put definitions in tooltips, not hidden documentation pages.
- Ship summary grains and pre-computed filters, never raw table secrets.
- Annotate refresh time and source grain on every published app.
Common mistakes
- Interaction with no structure — users free-plot fields and 'find' nonsense
- Dropping a raw database connection into a dashboard app.
- Interactive charts that reset definitions per click, breaking comparisons.
- Over-shopped hovers burying the actual numbers.
Debugging tips
- A blank interactive chart → check the DataFrame got passed and the Express call compiles.
- Hover showing wrong grain → confirm what column is bound and its dtype.
- Streamlit freezing on filter → small data pulled per render; move to precomputed aggregates.
- When two filter paths disagree, unify the source grain and the filter binding.
Interview checkpoint
Quick quiz
Plotly and Altair both:
Interactive charts should expose the raw database connection to users.