Data Analysis with pandas · pandas Fundamentals

Selecting and Filtering Rows and Columns

Select data by label with loc, by position with iloc, filter rows with boolean conditions and isin, and use query for readable filters.

Create a free account to save this page, take notes and track your progress. Sign in

What you'll build

Answers to everyday questions about the orders table: orders from Germany, orders worth more than 20 euros, specific customers, and particular columns, using the three selection tools pandas provides.

The idea

  • df["col"] / df[["a", "b"]]: columns.
  • df.loc[rows, cols]: by label (index values and column names), including boolean masks.
  • df.iloc[rows, cols]: by position (0, 1, 2...).
  • Boolean masks combine with & (and), | (or), ~ (not), each condition in parentheses.
  • isin([...]) tests membership; between(a, b) ranges; query("...") reads like a sentence.

The code

loc, iloc and boolean filtersTry it yourself
from io import StringIO
import pandas as pd

csv = StringIO("""order_id,date,customer,country,product,quantity,unit_price
1001,2026-01-03,ana,DE,mug,2,8.50
1002,2026-01-03,ben,US,teapot,1,24.00
1003,2026-01-04,chen,DE,kettle,1,31.90
1004,2026-01-05,ana,DE,teapot,1,24.00
1005,2026-01-07,dara,FR,mug,4,8.50
1006,2026-01-07,ben,US,mug,1,8.50
""")
orders = pd.read_csv(csv, parse_dates=["date"])

orders["total"] = orders["quantity"] * orders["unit_price"]

german = orders.loc[orders["country"] == "DE", ["order_id", "customer", "total"]]
print(german)

big_or_fr = orders[(orders["total"] > 20) | (orders["country"] == "FR")]
print(big_or_fr["order_id"].tolist())

print(orders.loc[orders["customer"].isin(["ana", "ben"]), "product"].unique().tolist())
print(orders.iloc[:2, :3])
print(orders.query("country == 'US' and quantity >= 1")["order_id"].tolist())

Output

   order_id customer  total
0      1001      ana   17.0
2      1003     chen   31.9
3      1004      ana   24.0
[1002, 1003, 1004, 1005]
['mug', 'teapot']
   order_id       date customer
0      1001 2026-01-03      ana
1      1002 2026-01-03      ben
[1002, 1006]

Common mistakes

  • Using and/or instead of &/|, or forgetting parentheses around each condition (ValueError: truth value of a Series is ambiguous).
  • Chained indexing like df[df.x > 1]["y"] = 0: in pandas 3 (copy-on-write) it never modifies df. Use df.loc[df.x > 1, "y"] = 0.
  • Mixing up loc (labels, inclusive end) and iloc (positions, exclusive end).

Key points

  • loc selects by label, iloc by position.
  • Combine boolean conditions with &, |, ~ and parentheses.
  • Assign with a single loc call, never chained indexing.

Further reading: Indexing and selecting data · Copy-on-Write

Practice questions

What's the difference between loc and iloc?

Answer

loc selects by labels (index values and column names, end inclusive); iloc selects by integer positions (end exclusive).

Why does (df.a > 1 and df.b < 5) raise an error?

Answer

Python's and/or need a single True/False; for element-wise logic on Series use & and | with parentheses around each condition.

Why doesn't df[df.x > 1]['y'] = 0 change df in pandas 3?

Answer

With copy-on-write, the first indexing returns a new object; assigning to it never affects df. Use df.loc[df.x > 1, 'y'] = 0.

Open in the app to mark lessons complete, take notes and track your progress.

Was this page helpful?