Pandas loc vs iloc and the slicing rule that bites

I have lost count of the data pipelines I have seen break on Pandas loc vs iloc. It is one of those small things that behaves perfectly in a local Jupyter notebook and then falls apart in production, usually the first time something re-indexes the DataFrame. Most developers use the two interchangeably right up until that moment.

The common advice is to use whichever one works, which is fine until the day it does not. If your backend depends on pulling exact rows out of a DataFrame, choosing a selector by trial and error is how you end up debugging at 3 AM.

Pandas loc vs iloc, in one line

The model is simple enough: loc is label-based and iloc is integer-position-based. loc reads the names in your index. iloc only cares which position the row sits in. Slicing is where the two stop behaving the way you would guess.

import pandas as pd

# The Naive Approach: Assuming they behave the same
df = pd.DataFrame({'Score': [90, 85, 88]}, index=[101, 102, 103])

# This retrieves row with LABEL 101
print(df.loc[101]) 

# This retrieves the FIRST row (index 0)
print(df.iloc[0]) 

Re-index the data and iloc[0] still hands you the first row, while loc[101] fails outright once that ID is gone. For heavier selection logic, I wrote a separate guide on how to filter Pandas DataFrames.

Slicing: one is inclusive, one is not

iloc slices the way the rest of Python does, with the stop index excluded. loc includes it. So df.loc[101:103] returns 101, 102 and 103, while df.iloc[0:2] returns only rows 0 and 1. Mix them up inside a loop and you get an off-by-one error that corrupts the output without raising anything.

Both are worth keeping open in a tab: the Pandas loc documentation and the iloc API reference.

When I reach for each one

The rule I stick to in my own projects:

  • loc for boolean filtering, like df.loc[df['math'] > 80], and for any index with meaningful keys such as user IDs or timestamps. The line ends up reading like what it means.
  • iloc for machine learning preprocessing, where labels do not matter, and any time you want the first or last N records regardless of their IDs.

One client’s machine learning model kept failing because they were using loc against an index that had duplicates in it. Switching to iloc fixed it, since positions stay unique even when labels are a mess.

If loc versus iloc bugs are eating your dev hours, I take on that kind of work. I have been wrestling with WordPress, Python and messy data pipelines since the early days.

The check to run on your next refactor

Select on what the data is, meaning the label, with loc. Select on where the data is, meaning the position, with iloc. The test I run before committing a selector: if I shuffled this DataFrame, would this line still return what I expect? If not, it is the wrong one.

author avatar
Ahmad Wael
I'm a WordPress and WooCommerce developer with 15+ years of experience building custom e-commerce solutions and plugins. I specialize in PHP development, following WordPress coding standards to deliver clean, maintainable code. Currently, I'm exploring AI and e-commerce by building multi-agent systems and SaaS products that integrate technologies like Google Gemini API with WordPress platforms, approaching every project with a commitment to performance, security, and exceptional user experience.