When should the shop hire more staff?
The owner of a bike hire shop wants to take on a summer worker. Which months need the extra help?
The answer is somewhere in 365 rows of numbers. Nobody can see it there. One bar chart shows it at a glance.
By the end of this lesson
Note
I can make a chart that answers a question.
Key words
| Word | What it means | Example |
|---|---|---|
| Chart | a picture of numbers | |
| Bar chart | a chart that compares groups with bars | |
| Axis | the scale along one side of a chart | |
| Total | all the values added up | sum |
| Mean | the total divided by how many values there are | |
| Dashboard | one page of charts that each answer a question |
The cells students fill in are left blank in this preview.
Before you start
Note
Press Start the lab. The terminal has no Python of its own, so each Run starts with docker exec jupyter. That runs one command inside the lab's container, which holds hires.csv: one row for every day of 2025.
Start from the question, not the chart
A good chart answers one question. So write the question first.
Then decide two things. Which column splits the days into groups? Which number do you want for each group? "Which weather is busiest?" groups by weather and takes the mean of hires. The Run below does exactly that.
Mean hires for each weather
docker exec jupyter python3 steps/weather.pyShown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Worked example: from question to chart
| Question | Group by | Number | Chart |
|---|---|---|---|
| Which weather is busiest? | weather | mean hires | Bar chart |
| Which months need more staff? | month | mean hires | Bar chart, months in order |
| Are weekends busier? | weekend or not | mean hires | Bar chart with two bars |
| Do warm days get more hires? | no groups | every day | Scatter: temperature across, hires up |
The cells students fill in are left blank in this preview.
A total or a mean?
A total adds up every value in a group. A mean divides that total by how many values there are.
Totals mislead when the groups are different sizes. 2025 had 131 sunny days but only 114 cloudy ones, so sunny days win on total partly because there were more of them. Type this cell into a new notebook to see the totals.
Cell: total hires for each weather
import pandas as pd
hires = pd.read_csv("hires.csv")
# sum adds up the hires in each group.
totals = hires.groupby("weather")["hires"].sum()
totalsA bar chart must be drawn honestly
Two things make a bar chart lie. The first is the order: pandas sorts month names A to Z, so April comes first. The months Run puts them back in calendar order.
The second is the axis. The axis Run draws the same weather means twice, once with the axis from 0 and once from 220, and compares how the bars look.
Mean hires for each month, in order
docker exec jupyter python3 steps/months.pyShown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
The same bars on two axes
docker exec jupyter python3 steps/axis.pyShown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
A common mistake
Warning
Many people think a bar chart's axis may start wherever it looks best. A bar's length is the number, so the axis must start at 0. From 220, sunny looks 12 times as busy as rainy. It is really about 1.4 times as busy.
A dashboard puts answers side by side
A dashboard is one page of a few charts. Each chart answers one question, and each has a title that says which.
This cell draws two bar charts beside each other. Type it under your totals cell and run it. Both axes start at 0, which pandas does for bar charts.
Cell: a two-chart dashboard
import matplotlib.pyplot as plt
# Month names in calendar order, not A to Z.
order = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
months = hires.groupby("month")["hires"].mean().reindex(order)
weather = hires.groupby("weather")["hires"].mean()
# One row of two charts, each with a title that is its question.
fig, axes = plt.subplots(1, 2, figsize=(10, 3))
months.plot.bar(ax=axes[0], title="Mean hires a day, by month")
weather.plot.bar(ax=axes[1], title="Mean hires a day, by weather")
plt.tight_layout()Going further: how busy is a usual day?
A histogram counts how many days fall into each band of hires, such as 250 to 299.
Type docker exec jupyter python3 steps/hist.py into the terminal and press Enter. Which band has the most days? Add a third chart to your dashboard that shows it.