Chapter 2 · Part 1

Selecting rows & columns

Having a table is only useful if you can reach the parts you care about — this column, those rows, everything above a threshold. pandas gives you three ways in: by column, by row, and by condition. We'll keep using the movies DataFrame from Chapter 1.

Columns

Grab one column with square brackets (you get a Series); grab several by passing a list of names (you get a smaller DataFrame):

columns.py
movies["title"]              # one column -> a Series
movies[["title", "rating"]]  # two columns -> a DataFrame
movies[['title', 'rating']]
title  rating
0     Inception     8.8
1    The Matrix     8.7
2  Interstellar     8.6
3      Parasite     8.5
4      Whiplash     8.5
5          Dune     8.0
6    La La Land     8.0
7          Coco     8.4

The double brackets trip everyone up at first: the outer [] means "select", the inner [] is the list of columns you're selecting.

Rows: .loc and .iloc

Two accessors, and the difference matters. .iloc selects by integer position (like a Python list); .loc selects by index label. Right now those happen to be the same numbers, but they diverge the moment you filter or sort:

rows.py
movies.iloc[0]           # the first row, by position -> a Series
movies.loc[3, "title"]   # row with label 3, column "title" -> "Parasite"
movies.iloc[0]
title     Inception
year           2010
genre        Sci-Fi
rating          8.8
votes          2400
Name: 0, dtype: object

The one that matters: boolean filtering

This is where pandas earns its keep. Write a condition on a column and you get a Series of True/False — a boolean mask. Put that mask in brackets and pandas keeps only the True rows:

filter.py
movies["rating"] >= 8.6      # a mask: True for the top-rated films

movies[movies["rating"] >= 8.6]   # keep only those rows
output
title  year   genre  rating  votes
0     Inception  2010  Sci-Fi     8.8   2400
1    The Matrix  1999  Sci-Fi     8.7   1900
2  Interstellar  2014  Sci-Fi     8.6   1800

Combine conditions with & (and) and | (or) — each condition must be wrapped in parentheses, because & binds tighter than >= in Python:

combine.py
# films from 2014 on that are also highly rated
movies[(movies["year"] >= 2014) & (movies["rating"] >= 8.5)]
output
title  year     genre  rating  votes
2  Interstellar  2014    Sci-Fi     8.6   1800
3      Parasite  2019  Thriller     8.5    780
4      Whiplash  2014     Drama     8.5    900

Notice the index is now 2, 3, 4 — filtering keeps each row's original label. That's exactly why .loc (by label) and .iloc (by position) part ways after a filter.

🎯 Your turn
From movies, select just the title and year columns for every film released in 2015 or later.

You can reach any slice of the table. Next, let's start changing it.