Unit 6 • Lesson 2

isin, between and query

Overview

Three ways to say a condition that reads like the question.

Intermediate 20–25 min

What You Will Learn in This Lesson

By the end of this lesson, you will be able to:

  • Test membership of a set with isin.
  • Test a range with between, and know which ends it includes.
  • Write a condition as a sentence with query.
  • Pick the form that reads closest to the question being asked.

Why This Matters

All three of these do things you could already do with masks. They matter because a filter you can read is a filter you can check, and a chain of six |s is not one. Choosing the clearest form is a correctness decision, not a style one.

Step 1: isin for a set of values

Testing against several values with a chain of == and | works and reads badly. isin takes the list.

1

The readable form

And it does not get longer as the list grows, which matters when the list comes from somewhere else.

import pandas as pd

df = pd.DataFrame({"subject": ["maths", "art", "computing"]})
print(df[df["subject"].isin(["maths", "computing"])])
2

Negating it

"Everything except these" is ~ in front of the whole thing.

import pandas as pd

df = pd.DataFrame({"subject": ["maths", "art", "computing"]})
print(df[~df["subject"].isin(["art"])])

Mini Practice #1: A list of subjects

Try It Yourself

Select the rows in maths or computing twice — once with | and once with isin — and compare which you would rather read.

Press Run to see output

Step 2: between for a range

between is inclusive at both ends by default, which is usually what a question means by "between 60 and 80".

1

Both ends included

One call instead of two comparisons and a pair of brackets.

import pandas as pd

df = pd.DataFrame({"score": [55, 60, 70, 80, 85]})
print(df[df["score"].between(60, 80)])
2

When you meant something else

Pass inclusive to change it. Saying so explicitly is better than writing two comparisons and hoping the reader checks them.

import pandas as pd

df = pd.DataFrame({"score": [55, 60, 70, 80, 85]})
print(df[df["score"].between(60, 80, inclusive="neither")])

Step 3: query for a condition that reads as a sentence

Inside query the string is parsed by pandas, so the ordinary words work and the brackets go away.

1

Plain and, plain or

Column names are bare, and a Python variable is reachable with an @ in front of it.

import pandas as pd

df = pd.DataFrame({"score": [92, 88, 60], "city": ["L", "Y", "L"]})
print(df.query("score > 80 and city == 'L'"))

mark = 85
print(df.query("score > @mark"))

query is not faster in any way that matters at this size. The argument for it is that the filter reads like the question, which is what makes it checkable.

Mini Practice #2: The same filter, three ways

Try It Yourself

Select scores from 60 to 80 inclusive with a pair of comparisons, with between, and with query.

Press Run to see output

Step 4: When to Use It

Membership in a list

isin replaces a chain of == with | when the allowed values are a set.

df[df["team"].isin(["red", "blue"])]

Ranges and readable conditions

between for inclusive ranges; query when the condition reads better as a sentence.

When Not to Use It

Do not reach for query when a column name has spaces or the condition uses outside variables you have not marked with @. A plain mask is clearer there.

End-of-Lesson Exercises

Exercise 1: Count the rows in a set of subjects

Write in_subjects(df, subjects) returning the number of rows whose subject is one of subjects.

df["subject"].isin(subjects) is the mask. Its sum is the count, and int() makes it a plain number.

Press Run to try it, then Check my work to mark it.

Exercise 2: Names in a band

Write band_names(df, low, high) returning the names whose score is between low and high inclusive, in the order they appear. Say the range once rather than as two comparisons.

df["score"].between(low, high) is inclusive at both ends by default. Mask the table with it, then take the name column.

Press Run to try it, then Check my work to mark it.