Data Science
Plotly foundations: interactive charts and useful hover data
Build interactive bar, scatter and line charts with deliberate hover fields and export them without a hosted account.
What you will learn
Build interactive bar, scatter and line charts with deliberate hover fields and export them without a hosted account.
Before you start
You need basic variables, lists and function calls, not advanced Python algorithms. If these are new, visit Python foundations first.
- Create a local environment:
python -m venv .venv. Activate it for your OS and installpython -m pip install jupyterlab numpy pandas matplotlib seaborn plotly. - Download the 12-row sales CSV into your notebook folder. Keep its filename unchanged.
- Start Jupyter with
jupyter lab. Run the setup below in a fresh notebook before every workshop.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import plotly.express as px
raw = pd.read_csv('data-science-sales.csv', parse_dates=['date'])
df = raw.copy()
df['revenue'] = df['units'] * df['unit_price']
net = df.loc[df['returned'].eq(0)].copy()
Data dictionary: each row is one order for one product; units is a positive count; unit_price is INR per unit; returned is 0 or 1. Revenue is units × unit_price. For this workshop, net sales exclude the entire returned order (not partial returns). The CSV has 12 rows, 4950 gross revenue, 4450 net revenue and 35 net units. This small fictional sample teaches technique; it does not justify population or causal claims.
Save your notebook and written interpretation. There is no browser code judge and no automatic grading of visual design.
Learn the idea
Plotly Express produces a Figure from a DataFrame. Define x, y, colour and hover fields deliberately: interactive does not mean understandable. Aggregate revenue before a business-total bar chart. update_layout sets titles and legend labels. write_html(include_plotlyjs=True) creates a larger self-contained file that works offline; using 'cdn' reduces file size but requires internet. These labs use local HTML and do not require Dash, an API key or a hosting service.
Follow a worked example
summary=net.groupby('region',as_index=False)['revenue'].sum()
fig=px.bar(summary,x='region',y='revenue',text='revenue',labels={'revenue':'Net revenue (INR)'},title='Regional net sales; returns excluded')
fig.write_html('regional-interactive.html',include_plotlyjs=True)
fig.show()
Expected result
Three interactive bars with totals 1350,1700,1400 and a standalone HTML file.
Skill-development workshop
These are practical assignments, not MCQs or code-judge puzzles. Work in your own notebook or MySQL client. Complete the levels in order; if a task feels difficult, follow the hint and compare with the reference only after making an attempt. Keep your result and a short explanation of what it means.
Easy: Create a product revenue bar chart.
Success criteria: Four bars, Lamp 2400, labelled INR.
Need a starting point? Show the hint
Use the same groupby product summary as the pandas lesson.
Reference solution — open after trying
summary=net.groupby('product',as_index=False)['revenue'].sum()
fig=px.bar(summary,x='product',y='revenue',labels={'revenue':'Net revenue (INR)'},title='Product net sales'); fig.show()
Medium: Include order id, product and region in scatter hover.
Success criteria: 11 points; hovering identifies an order without exposing any personal data.
Need a starting point? Show the hint
Pass hover_data as a column list.
Reference solution — open after trying
fig=px.scatter(net,x='units',y='revenue',color='region',hover_data=['order_id','product'],labels={'revenue':'Order revenue (INR)'},title='Order units and revenue'); fig.show()
Hard: Plot sorted monthly net revenue with custom labels.
Success criteria: 1100,1550,1800 in chronological order with markers; month labels preserved.
Need a starting point? Show the hint
Create a month string after dt.to_period and sort before px.line.
Reference solution — open after trying
m=net.assign(month=net['date'].dt.to_period('M').astype(str)).groupby('month',as_index=False)['revenue'].sum().sort_values('month')
fig=px.line(m,x='month',y='revenue',markers=True,labels={'revenue':'Net revenue (INR)'},title='Monthly net sales'); fig.show()
Professional: Deliver an offline interactive report plus a data alternative.
Success criteria: HTML includes plotly.js, CSV reconciles to 4450, file opens without a hosted account. State that embedding JS makes the file larger.
Need a starting point? Show the hint
write_html with include_plotlyjs=True; export the same summary.
Reference solution — open after trying
s=net.groupby('region',as_index=False)['revenue'].sum()
fig=px.bar(s,x='region',y='revenue',text='revenue',title='Q1 2026 net revenue (INR); returns excluded')
fig.write_html('offline-sales.html',include_plotlyjs=True,full_html=True)
s.to_csv('offline-sales-data.csv',index=False)
assert s['revenue'].sum()==4450
Reflection and submission
Save your queries/notebook and outputs. Write three sentences: what you changed, how you checked it, and one limitation. A correct chart or query without a clear interpretation is not a completed professional assignment.
summary=net.groupby('region',as_index=False)['revenue'].sum()
fig=px.bar(summary,x='region',y='revenue',text='revenue',labels={'revenue':'Net revenue (INR)'},title='Regional net sales; returns excluded')
fig.write_html('regional-interactive.html',include_plotlyjs=True)
fig.show()Lesson Code (python)
summary=net.groupby('region',as_index=False)['revenue'].sum()
fig=px.bar(summary,x='region',y='revenue',text='revenue',labels={'revenue':'Net revenue (INR)'},title='Regional net sales; returns excluded')
fig.write_html('regional-interactive.html',include_plotlyjs=True)
fig.show()Console Output
Three interactive bars with totals 1350,1700,1400 and a standalone HTML file.Up next · Continue learning
subplots and an analytical handoff
Compose an offline two-panel sales report with definitions, source data and a clear business conclusion.