A real data set in Python: read a CSV, count, average and find the biggest, draw a bar chart, clean messy data and check it with test cases, then build a dashboard.
Each lesson works two ways. Students can work through the online tutorial at their own pace (it checks their answers and saves their progress in their browser), or you can teach it to the whole class from the slides, then send students into the tutorial for the Modify and Make steps.
Every lesson guide has plain-language notes, the answers to every check, a solution for every task, and slides and a worksheet for Waypoints Prepare. These guide pages are not linked from student pages, but they are not secret either: keep printed Teacher editions for answers you do not want students to find.
Whole-course cheat sheet: Open to print (every command, grouped by unit: a handout for the final challenge)
Read a CSV file into a list of dictionaries, then count, filter, total and average it.
A CSV file is a table saved as plain text: the first line names the columns, every other line is a row, and commas separate the values. Python's csv.DictReader reads it into a list of dictionaries, one per row, so songs[0]["title"] is the first song's title. Every value comes in as text: "2013", not 2013. int() and float() turn it into a number before you compare or add.
Questions about data are loops. Pick rows with a loop and an if. Count them with a variable that goes up by one. Add up a column with a total that starts at 0. Divide by the count for an average. Keep the biggest so far: start with the first row, and replace it only when a row beats it.
if.A stack of index cards, one per song, each with the same labelled boxes. Reading the data is flipping through the stack; a total is a running sum on a scrap of paper. It breaks because the cards say "3.9" in ink: Python treats it as writing, not a number, until you convert it.
music.csv in the playground's Files tab and find the first song."rock" to "K-pop".music.csv is 49 well-known songs compiled for these lessons (lengths are rounded). Any CSV with a name, a category, a year and a number works with the same programs once the keys change: a class survey, sports results, a Wikidata export of films or games your students like. Students add a file with Add a file from this computer in the playground's Files tab.
+ joins text.Cheat sheet: Open to print (A4, with a picture of what each command draws) · Markdown
Draw a bar chart from counts, then clean messy data and check your code with test cases.
Counting with a dictionary. One key per value (each genre), and its count as the value. For each row: if the key is there, add 1; otherwise start it at 1. A second loop over the dictionary draws a bar for each key: "#" * count repeats the character that many times.
Cleaning. Real data has blanks, typos, numbers in words and impossible values. A small cleaning function takes one messy value and gives back a good value, or None ("no value") when it cannot be used. The loop skips the None rows, and the result says how many answers it used.
Test cases. assert clean_hours("400") is None is a test: silent when true, and the program stops with AssertionError when false. A few tests prove the function works, and catch it the moment someone breaks it.
Counting is tally marks on a whiteboard, one row per genre; the bar chart is the tally marks themselves. Cleaning is a teacher reading survey slips: "Pop", "pop " and "POP" are the same answer, and "400 hours" goes in the bin. It breaks because a computer never guesses: every rule a human applies without thinking must be written down, and tested.
print(counts) after the first loop.survey.csv in the Files tab and spot four kinds of mess.168 to 16, run, and read the AssertionError. Put it back.is None and not == None? Both work here; is is the usual Python way to check for None.Cheat sheet: Open to print (A4, with a picture of what each command draws) · Markdown
Put the data behind a small app, then ask a real API for live data (optional).
pandas reads a CSV into a table (a DataFrame) in one line, pd.read_csv("music.csv"), and keeps numbers as numbers. songs[songs["genre"] == "pop"] keeps the rows where the test is true: the loop and if from Lesson 1 in one line.
Gradio turns a function into an app. gr.Interface(fn, inputs, outputs) draws an input for each item in inputs and an output for each in outputs; pressing Submit calls the function with the inputs' values, in order, and shows what it returns, in order. A dashboard is a function that filters the table, returning a table and a chart.
The playground runs a small stand-in for Gradio so it works in the browser. The same file runs unchanged in real Gradio (pip install gradio pandas), and a teacher can host it as a Hugging Face Space (accounts need age 13+).
A vending machine: buttons are the inputs, the machinery inside is the function, the tray is the output. It breaks because a Gradio function can be changed in a minute, and the same machine can serve any data.
inputs, one parameter in the function.Cheat sheet: Open to print (A4, with a picture of what each command draws) · Markdown