JIT — Intro to Data Science · Python Lab · Problem 22 of 30

Picking columns and filtering rows

A mask that brings whole rows with it — and a dozen wrong answers that look exactly as tidy as the right one.

Asking a table a question

Problem 21 told you what was in the file. This one starts using it: work out a new column from two existing ones, keep only the columns worth looking at, and keep only the rows that matter.

A new column from old ones df["percent"] = df["classes_attended"] / df["classes_held"] * 100
Two whole columns divided by each other, row by row, exactly as in problem 18 — no loop. Assigning to a column name that does not exist yet creates it, the same way writing to a new key created one in the dictionary in problem 8.
One pair of brackets or two, again df["name"] is one column as a Series.
df[["name", "percent"]] is a list of column names inside the brackets, and what comes back is a table with those columns in that order.
The inner brackets are the list. That is why picking several columns needs two pairs and picking one needs only one.
A mask picks rows, not just values df["percent"] < 80 gives one True or False per row, exactly like the NumPy mask in problem 19.
Put it back inside the square brackets — df[df["percent"] < 80] — and you get the whole rows where it was True. Each student's name and city comes along with their attendance, because rows stay together. That is the thing a table does that three separate lists never could.
Notice the index numbers that come back: 1, 3, 5. They are the original row numbers, not a fresh count, so you can always tell where a row came from.
New word — loc df.loc[rows, columns] asks for both at once: which rows, and which columns of them.
df.loc[df["percent"] < 80, "name"] reads as the names of the students below 80. The mask on the left chooses rows; the name on the right chooses what to show. It is the same selection you could do in two steps, said in one.
Nothing here will raise an error Almost every wrong choice in this problem produces a perfectly ordinary table. Filter on the wrong column and you get rows. Invert the comparison and you get rows. Count the wrong thing and you get a number. Pandas has no way of knowing which question you meant to ask — reading the answer is your job, and it is the whole job.

What you are building

name city classes_held classes_attended percent 0 Anjali Nagpur 40 36 90.0 1 Farhan Pune 40 31 77.5 2 Priya Nagpur 40 40 100.0 name percent 0 Anjali 90.0 1 Farhan 77.5 2 Priya 100.0 name city classes_held classes_attended percent 1 Farhan Pune 40 31 77.5 3 Rohit Mumbai 40 22 55.0 5 Imran Pune 40 29 72.5 Below 80%: 3 students 1 Farhan 3 Rohit 5 Imran Name: name, dtype: str
Coming later This file is complete. The messy one from problem 21 has a gap in it, and a gap changes what a filter does — a comparison against a missing value is neither True nor False. That is problem 23.

Build the programme

Your plan

The steps still to place

The whole programme is laid out below. Five pieces are missing. Only one of them can stop the programme; the other twelve wrong choices all hand you a tidy, plausible, wrong answer.

Leave nothing on "choose…". A wrong pick does not always cause an error — sometimes it just prints something you did not expect, which is the harder kind of mistake to spot.

Run and read

Here is the whole programme, reading the tidy file from problem 21. The cutoff is yours to change — try 60, where only one student falls below, and 100, where nearly everybody does.

Your programme

Output

Nothing has run yet.