Chapter 02
Selecting rows and columns
Picking columns, the difference between loc and iloc, the index, and how copy-on-write changes what happens when you modify a selection.
Selecting columns
- What
- Square brackets with one name return a Series; with a list of names they return a DataFrame with those columns in that order.
- Why
- Most analysis starts by narrowing a wide table to the handful of columns a question needs.
df["amount"]
df[["date", "region", "amount"]]
df.filter(like="price")Watch out
Using attribute access like df.amount: it breaks for names with spaces or names that clash with methods such as count.
loc: select by label
Also called .loc
- What
df.loc[rows, cols]selects by index labels and column names, and accepts boolean masks. Label slices include both ends.- Why
- It is the one clear way to select and assign in a single step, which matters now that chained assignment is gone.
df.loc[df["amount"] > 1000, ["region", "amount"]]
df.loc["2026-01-01":"2026-01-31"] # dated index, both ends
df.loc[df["region"] == "North", "flag"] = Trueiloc: select by position
Also called .iloc
- What
df.iloc[rows, cols]selects by integer position, like Python lists: the end of a slice is excluded.- Why
- Useful when position is what you mean, such as the first ten rows or the last column, whatever their labels are.
df.iloc[:10]
df.iloc[:, -1]
df.iloc[[0, 5], [1, 2]]Watch out
Mixing up loc and iloc on an integer index: loc[0:5] returns six rows, iloc[0:5] returns five.
The index
Also called set_index, reset_index, row labels
- What
- The index is the set of row labels.
set_indexturns a column into the index andreset_indexturns the index back into a column. - Why
- A meaningful index, such as a date or an ID, makes lookups, alignment and time series resampling simple.
df = df.set_index("order_id")
df.loc[10432]
df = df.reset_index()Watch out
Forgetting that arithmetic between two Series aligns on the index, so mismatched labels silently produce NaN.
Copy-on-write
Also called CoW, SettingWithCopyWarning, chained assignment
- What
- Since pandas 3.0 every selection or method result behaves as a new object: changing it never changes the original. pandas only copies data when you actually modify it.
- Why
- It ends the old confusion over views and copies and removes
SettingWithCopyWarning, but chained assignment such asdf["a"][0] = 1no longer modifiesdf.
# does nothing to df under copy-on-write
df[df["amount"] < 0]["amount"] = 0
# do it in one step instead
df.loc[df["amount"] < 0, "amount"] = 0Watch out
Copying old tutorials that assign through two sets of brackets and wondering why the data never changes.
Sampling rows
Also called sample, nlargest, nsmallest
- What
sample(n)orsample(frac=0.1)picks random rows;nlargestandnsmallestreturn the top or bottom rows by a column.- Why
- Sampling makes exploring a big dataset fast, and
nlargestanswers top-10 questions without sorting everything.
df.sample(frac=0.05, random_state=42)
df.nlargest(10, "amount")