Filtering with query() & eval()

df.query() filters rows using a plain-English string expression — like "age > 30 and city == 'NYC'" — instead of stacking bracketed boolean masks.

Learn Filtering with query() & eval() in our free Pandas course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a…

Part of the free Pandas course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

Learn to write readable multi-condition filters, reference Python variables with @, compute new columns with eval(), and know when string expressions beat boolean masks.

What You'll Learn in This Lesson

1 Readable Filters — df.query("...")

df.query() takes a string and keeps the rows where it is true. Inside the string you write column names bare — no df["..."] — and you may use the friendly words and , or , and not instead of the bitwise & , | , ~ . A filter that needs three sets of brackets as a mask becomes one clean sentence.

2 Using Variables — the @ Reference

Filters are rarely hard-coded — the threshold often lives in a variable. Inside a query string, prefix a Python variable with @ to use its value. df.query("age > @cutoff") reads cutoff from your code. Without the @ , query assumes you mean a column called cutoff and raises an error when it cannot find one.

3 Computing Columns — df.eval()

Where query() selects rows, eval() calculates values. Hand it an arithmetic expression over your columns and it returns the result; use the "new = ..." form to attach it as a column. It keeps long formulas readable and, on big frames, can run faster by avoiding temporary intermediate arrays.

! Common Errors (And How to Fix Them)

An unquoted string value is read as a variable name:

🎯 Mini Challenge: Filter and Compute Orders

Use query and eval together on an orders table.

❓ Frequently Asked Questions

Lesson complete — your filters read like English!

You can filter with df.query() , combine clauses with and / or , inject variables with @ , and compute new columns with df.eval() .

🚀 Up next: Replacing Values — swap, blank out, and clamp values with replace, where, and mask.

Practice quiz

What does df.query() return?

  • The rows where the expression is true
  • A single boolean value
  • The column names only
  • A sorted copy of the frame

Answer: The rows where the expression is true. query() keeps the rows for which the string expression evaluates to True.

Inside a query string, how do you reference a Python variable named cutoff?

  • #cutoff
  • @cutoff
  • $cutoff
  • %cutoff

Answer: @cutoff. Prefix the variable with @, e.g. df.query('age > @cutoff').

Which method computes a new column from an expression?

  • df.filter()
  • df.select()
  • df.eval()
  • df.where()

Answer: df.eval(). df.eval('total = price * qty') evaluates the expression and can attach it as a column.

How must a string value be written inside a double-quoted query?

  • Left unquoted, like NYC
  • With backticks, like

Wrap text values in single quotes so they are not read as variable names: city == 'NYC'.

Which words can replace &, |, ~ inside a query expression?

  • and, or, not
  • AND, OR, NOT only
  • plus, minus, no
  • with, without, none

Answer: and, or, not. query() accepts the readable keywords and, or, and not.

What does df.query('city in @cities') do?

  • Adds a cities column
  • Keeps rows whose city is in the list cities
  • Sorts by city
  • Renames the city column

Answer: Keeps rows whose city is in the list cities. in with @list is the readable equivalent of .isin() on a boolean mask.

By default, df.eval('total = price * qty') returns what?

  • Nothing, it mutates in place silently
  • A plain Python list
  • A new DataFrame with the extra column
  • Only the total Series

Answer: A new DataFrame with the extra column. It returns a new DataFrame with the computed column, so assign it back.

What error appears for df.query('city == NYC')?

  • SyntaxError: invalid token
  • ValueError: bad expression
  • KeyError: NYC
  • name 'NYC' is not defined

Answer: name 'NYC' is not defined. Unquoted NYC is treated as a variable name; quote it as 'NYC'.

Why might query()/eval() run faster on large frames?

  • They can use the numexpr engine and avoid temporary arrays
  • They skip type checking entirely
  • They cache every result to disk
  • They run on the GPU automatically

Answer: They can use the numexpr engine and avoid temporary arrays. pandas can evaluate the expression with numexpr, avoiding intermediate arrays.

Given df with age column, what does df.query('age > 30')['name'] return?

  • The whole DataFrame
  • The name values for rows where age exceeds 30
  • A count of matching rows
  • The age column instead

Answer: The name values for rows where age exceeds 30. query() filters rows first, then ['name'] selects that column from the result.

Continue this course