loc vs iloc: Label vs Position
loc and iloc are the two precise indexers in pandas: loc selects rows and columns by their labels (names), while iloc selects them by their integer position — together they give you exact, unambiguous access to any cell or block of a DataFrame.
Learn loc vs iloc: Label vs Position in our free Pandas course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick…
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 inclusive vs exclusive slicing, masking with .loc, safely setting values, and how to dodge the dreaded SettingWithCopyWarning.
What You'll Learn in This Lesson
1 .loc — Selection by Label
df.loc[row_label, col_label] selects using the names in the index and columns. To make the difference obvious, we'll use a custom string index.
2 .iloc — Selection by Position
df.iloc[row_pos, col_pos] ignores labels entirely and uses integer positions , starting at 0 — exactly like indexing a Python list. Slices are exclusive of the end.
- df.loc["alice":"carol"] → 3 rows (end label included )
- df.iloc[0:3] → 3 rows; df.iloc[0:2] → 2 rows (end excluded )
3 Masking and Setting Values with .loc
.loc accepts a boolean mask as its row selector, and — crucially — it's the safe way to set values. You can select rows by condition and a column to update in a single call.
⚠️ The SettingWithCopyWarning Trap
This is the most infamous pandas gotcha. It happens when you chain two indexing operations and then assign — pandas can't tell whether you're editing the original or a temporary copy, so your change may silently vanish.
Rule: if you see two sets of square brackets back to back on the left side of an = , rewrite it as a single .loc[rows, cols] = value .
📋 Quick Reference
Aspect
.loc
.iloc
Selects by
Label (name)
Integer position
Slice end
Inclusive
Exclusive
Boolean mask
✓ Yes
✗ No
Example
df.loc["bob", "age"]
df.iloc[1, 0]
🎯 Mini Challenge: Precise Access
Use both indexers and a safe set operation on the same table.
- Grab the last two rows with .iloc
- Grab a label slice with .loc (notice it's inclusive)
- Use a masked .loc assignment to discount cheap items
❓ Frequently Asked Questions
Lesson complete — you have surgical control over your data!
You can select by label with .loc (inclusive slices), by position with .iloc (exclusive slices), filter with masks, set values safely, and avoid the SettingWithCopyWarning.
🚀 Up next: Adding, Modifying & Dropping Columns — reshape your DataFrame's structure.
Practice quiz
What does .loc select by?
- Integer position
- Label (the index and column names)
- Data type
- Memory address
Answer: Label (the index and column names). loc selects by label — the names you see in the index and columns.
What does .iloc select by?
- Integer position, starting at 0
- Label
- Column dtype
- Sort order
Answer: Integer position, starting at 0. iloc uses integer positions like a Python list, starting at 0.
For an index ['alice','bob','carol'], how many rows does df.loc['alice':'bob'] return?
- 1
- 2
- 3
- 0
Answer: 2. loc slices are inclusive of the end label, so alice and bob = 2 rows.
How many rows does df.iloc[0:2] return?
- 3
- 1
- 0
- 2
Answer: 2. iloc slices are exclusive of the end, so positions 0 and 1 = 2 rows.
Which indexer accepts a boolean mask as its row selector?
- .loc
- .iloc
- Both equally
- Neither
Answer: .loc. loc accepts a boolean mask; iloc only takes integer positions.
What is the safe way to set values on filtered rows?
A single df.loc[rows, cols] = value call edits the original safely.
What triggers the SettingWithCopyWarning?
- Using .loc once
- Chained indexing then assignment
- Reading a column
- Sorting the index
Answer: Chained indexing then assignment. Chaining two indexing ops (e.g. df[mask]['col'] = x) may edit a copy, raising the warning.
What does df.iloc[-1] return?
- The first row
- An error
- The last row by position
- The index name
Answer: The last row by position. Negative positions count from the end, like Python lists, so -1 is the last row.
For index ['alice','bob','carol'], how many rows does df.loc['alice':'carol'] return?
- 2
- 0
- 1
- 3
Answer: 3. loc end label is included, so alice, bob and carol = 3 rows.
Why must each condition in a multi-mask .loc use parentheses with & ?
- & binds tighter than comparison operators
- It runs faster
- loc requires double quotes
- Purely stylistic
Answer: & binds tighter than comparison operators. & has higher precedence than > or ==, so parentheses force the comparisons first.
Continue this course
- Previous: Filtering with Boolean Masks
- Next: Adding, Modifying & Dropping Columns