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.

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.

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.

.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.

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 .

Use both indexers and a safe set operation on the same table.

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.