← Data detective

Rows of data

Read a CSV file into a list of dictionaries, one per row, then pick out the rows you want.

Spreadsheets, sports tables and music charts can all be saved as a CSV file: plain text that Python can read row by row.

A CSV file (comma-separated values) is a table saved as plain text: the first line names the columns, and every other line is one row. This course uses music.csv, a table of well-known songs. It is already in your Files tab; open it there to see what it looks like. Python reads each row into a dictionary, which looks a value up by its name (its key): song["title"].

PredictRead the code and say what it will do before you run anything. A wrong guess is fine: it shows you what to look for.

Predict

rows.py
song = {"title": "Royals", "year": "2013"}
print(song["year"] + "1")

The year is in quotes. What does + do with two pieces of text?

What does it print?

RunRun it and compare the result with your prediction.

Run

Run it. It prints how many songs there are, the first song, then the rock songs. Change "rock" to "K-pop" and run it again.

rows.py
import csv

with open("music.csv") as f:
    songs = list(csv.DictReader(f))

print(str(len(songs)) + " songs")
print(songs[0])
for song in songs:
    if song["genre"] == "rock":
        print(song["title"] + " by " + song["artist"])
Try it yourselfYour edits are saved in this browser.

InvestigateTrace how each line of code connects to what you see.

Investigate

rows.py
import csv

with open("music.csv") as f:
    songs = list(csv.DictReader(f))

print(str(len(songs)) + " songs")
print(songs[0])
for song in songs:
    if song["genre"] == "rock":
        print(song["title"] + " by " + song["artist"])

What one row of the table becomes.

A row, then a key.

A comparison that does not work.

What is songs[0]?

How would you get the artist of the third song?

This should list the songs from 2020 on, but it stops with TypeError: '>=' not supported between instances of 'str' and 'int'. Click the line that is wrong.

ModifyChange the code on purpose and check the result.

Modify

List only the songs from 2010 or later. The year has to become a number first.

Need a hint?

Change the if to compare the year as a number: int(song["year"]) >= 2010.

Count the pop songs and print the total at the end.

Need a hint?

Before the loop, count = 0. Inside the if, count = count + 1.

Another hint

After the loop (not indented), print the count.

Try it yourselfYour edits are saved in this browser.

List the songs from 2010 or later.

    Run your program. This ticks when your code does all of the above.

    Count the pop songs and print how many there are.

      Run your program. This ticks when your code does all of the above.

      MakeBuild something new using what you have learned. Expect a few tries; that is normal.

      A genre finder

      Ask which genre to look for, list each of its songs with its year, and finish with how many there were. Make it work whether someone types pop, Pop or POP.

      Try it yourselfYour edits are saved in this browser.

      Ask for a genre, list its songs, and say how many there are.

        Run your program. This ticks when your code does all of the above.

        Info

        Where this leads

        Every data tool, from spreadsheets to big databases, works on rows and columns like this. Next: totals, averages and the biggest value.

        Your teacher gives you films.csv with the columns title, studio, year, rating. What would you change in your genre finder?

        For teachers

        Students read music.csv into a list of dictionaries with csv.DictReader, find values by row and key, learn that every value from a CSV is text, then filter and count rows and build a genre finder. About 50 minutes.

        Open the teacher guide: answers, solutions, slides and a worksheet.

        Students will be able to

        Before class

        Read the unit primer first. This course runs in the Python playground (real Python in the browser, Pyodide). The first load takes a few seconds; before teaching it, open the site's Check your school page once on a student device at school. music.csv appears in each student's Files tab by itself (the Files tab can put the lesson's copy back, or add a CSV from the computer). csv.DictReader(f) reads the first line as column names and makes every other line a dictionary; list(...) keeps them all. Every value is text, so "2013" + "1" is "20131" (the Predict) and comparing a year with a number fails (the bug task) until int() changes it. Dictionaries are introduced here only as far as reading one (song["title"]: a value looked up by its key); Deeper Python goes further. with open(...) is a recipe here (copy the lines), taught properly in Deeper Python's Save the game.

        Running the lesson

        1. Predict: write "2013" + "1" on the board, then 2013 + 1. Quotes make text.
        2. Run: have students open music.csv in the Files tab and match the first row with songs[0].
        3. Investigate: count from 0 together: songs[0] is the first song.
        4. Modify: the count goes up inside the if; the print goes after the loop.
        5. Make: test with pop, Pop and a genre that is not there.

        The hard part (on purpose)

        The bug task and the first Modify: realising every value is text. Ask students to print one value with type() and predict before fixing.

        When students get stuck

        Stretch and support

        Stretch: Ask for a year as well, and list only that genre's songs from that year on.

        Support: Give students the loop with the if already written, and ask them only to add the count.

        Where it leads

        Next lesson: totals, averages and the longest song. Swapping in another CSV with the same idea (a class survey, sports results) keeps every program working with new keys.

        What each step is for

        Now you can
        Next lesson2. Totals and the biggestAdd up a column, divide for the average, and keep the biggest so far, one row at a time.