pandas iloc: Select Rows and Columns by Position

Quick answer: Use DataFrame.iloc for zero-based, position-based selection. The first selector chooses rows and the second chooses columns, so df.iloc[2, 1] selects one cell, df.iloc[:3] selects the first three rows, and df.iloc[:, [0, 2]] selects two columns by position.

Python Pool infographic showing pandas iloc row and column positions, slices, lists, masks, and assignment
iloc selects by integer position: rows come first, columns second, and slices follow normal Python stop-exclusive rules.

pandas.DataFrame.iloc selects rows and columns by integer position. It does not use index labels or column names, so 0 means the first row or first column position.

The main references are the official DataFrame.iloc documentation, the pandas indexing guide, and the DataFrame.iat documentation.

Use iloc when your logic depends on position: the first row, last column, rows two through five, or a list of row numbers. Use loc when your logic depends on labels.

After selecting several 0/1 or Boolean columns, summarize them by label instead of repeatedly slicing positions. See the pandas binary indicator summary for vectorized counts, rates, missing-value checks, and grouped results.

The most common pattern is df.iloc[row_selector, column_selector]. The row selector appears before the comma, and the column selector appears after it.

Selectors can be integers, slices, lists of integers, or boolean arrays. That makes iloc flexible enough for quick inspection and for repeatable transformations in scripts.

Because iloc ignores labels, it is often the right tool after sorting, resetting an index, reading a file with default row numbers, or slicing by table position in a report.

Create A Small DataFrame

The examples below use a compact table so the selected positions are easy to see.

import pandas as pd

df = pd.DataFrame(
    {
        "name": ["Ada", "Grace", "Linus", "Guido"],
        "score": [98, 95, 88, 91],
        "team": ["A", "B", "A", "B"],
    }
)

print(df)

The first row is position 0, the second row is position 1, and so on. Column positions follow the displayed column order.

If you reorder the DataFrame, positions can point to different data. That is expected because iloc is position-based.

When teaching or debugging iloc, print the DataFrame first and count positions from the displayed output. That prevents mixing up row labels with row positions. Positional selection does not remove pandas label alignment; before comparing frames, use Fix Identically Labeled DataFrame Objects to align or reset their indexes and columns deliberately.

Select Rows By Position

Pass one integer to get a single row as a Series. Pass a slice to get multiple rows as a DataFrame.

import pandas as pd

df = pd.DataFrame({"name": ["Ada", "Grace", "Linus"], "score": [98, 95, 88]})

first_row = df.iloc[0]
first_two_rows = df.iloc[0:2]
last_row = df.iloc[-1]

print(first_row)
print(first_two_rows)
print(last_row)

Slice stop values are exclusive, just like normal Python slicing. 0:2 selects positions 0 and 1.

Negative positions count from the end, so -1 selects the last row.

A single out-of-range integer position raises an error. Slices are more forgiving, so a slice that extends beyond the DataFrame can return the available rows instead of failing in the same way.

Python Pool infographic showing a pandas DataFrame row and column positions for iloc selection
Integer positions: A pandas DataFrame row and column positions for iloc selection.

Select Rows And Columns

Add a comma to select both row positions and column positions.

import pandas as pd

df = pd.DataFrame(
    {"name": ["Ada", "Grace", "Linus"], "score": [98, 95, 88], "team": ["A", "B", "A"]}
)

name_and_score = df.iloc[0:2, 0:2]
score_column = df.iloc[:, 1]
single_value = df.iloc[1, 1]

print(name_and_score)
print(score_column)
print(single_value)

: means all rows or all columns in that axis. In this example, df.iloc[:, 1] selects every row from the second column.

A single row and single column position returns a scalar value. A slice usually keeps the result as a Series or DataFrame.

Use Lists Of Positions

Lists let you choose positions that are not next to each other.

import pandas as pd

df = pd.DataFrame({"name": ["Ada", "Grace", "Linus", "Guido"], "score": [98, 95, 88, 91]})

chosen_rows = df.iloc[[0, 3]]
chosen_cells = df.iloc[[0, 3], [0, 1]]

print(chosen_rows)
print(chosen_cells)

The order of positions in the list controls the order of the result.

Use lists when the positions come from another calculation, such as top-ranked rows after sorting.

Use Boolean Masks With iloc

iloc can use a boolean array-like selector when its length matches the axis length.

import pandas as pd

df = pd.DataFrame({"name": ["Ada", "Grace", "Linus"], "score": [98, 95, 88]})

mask = [True, False, True]
selected = df.iloc[mask]

print(selected)

This mask keeps the first and third rows. The mask is positional, so each boolean corresponds to a row position.

For label-aware boolean filtering, a normal Series condition with loc is often clearer.

Python Pool infographic comparing iloc scalar, list, slice, boolean, and callable selection
Slice selection: Iloc scalar, list, slice, boolean, and callable selection.

Assign Values With iloc

You can assign through iloc when you need to update cells by position.

import pandas as pd

df = pd.DataFrame({"name": ["Ada", "Grace", "Linus"], "score": [98, 95, 88]})

df.iloc[2, 1] = 90
df.iloc[0:2, 1] = [99, 96]

print(df)

The assigned shape must match the selected shape. A single scalar can fill one cell, while multiple cells need a compatible list, array, or Series.

For one scalar lookup or assignment, iat is a more direct position-based option. Use iloc for slices, lists, masks, and mixed row-column selections.

The practical rule is simple: choose iloc for integer positions and loc for labels. When code becomes hard to read, name the selected row and column positions before applying them.

If you need one fast scalar value, compare iat with iloc. df.iat[row, column] is built for a single cell by integer position, while df.iloc is the broader indexer for rows, columns, lists, and slices.

For production data work, prefer readable selector names over magic numbers. Assign positions such as score_col = 1 only when the table schema is stable, and add tests that fail when the column order changes.

Also check the result type after a selection. A single row may become a Series, a two-axis slice may stay a DataFrame, and a single row-column pair may return a scalar. Knowing the result shape helps you avoid follow-up errors.

Read The Two Selector Positions

The syntax is df.iloc[row_selector, column_selector]. An integer returns a scalar or Series depending on the other selector, while a slice or list generally preserves a DataFrame. Start by checking shape and columns so positions refer to the frame you think you have.

Python Pool infographic mapping row positions and column positions to a selected DataFrame
Rows and columns: Row positions and column positions to a selected DataFrame.

Use Python Slice Rules

iloc slices are zero-based and stop-exclusive, just like ordinary Python sequences. df.iloc[:5] includes positions 0 through 4. Unlike label-based indexing, the selection is not driven by index names, so a shuffled or custom index does not change the positions.

Select Lists And Boolean Arrays Carefully

A list such as [0, 3] selects exact positions, while a boolean array must align with the selected axis. Check its length and dtype before use. A boolean Series with labels belongs with label-aware operations rather than being passed casually to iloc.

Assign Without Ambiguity

Position-based assignment is useful for a known rectangular slice, but chained indexing can make it unclear whether an operation changes the original frame. Select the target with iloc in one expression and assign the new values with a shape that matches.

Python Pool infographic testing out-of-bounds, negative indices, shape, labels, and validation
iloc checks: Out-of-bounds, negative indices, shape, labels, and validation.

Know The Difference From loc

Use iloc when the question is where a value sits, and loc when the question is which label it has. Mixing those mental models is a common source of wrong rows, unexpected slices, and KeyError or IndexError exceptions.

Test Shape And Empty Cases

Test a one-row frame, empty selection, out-of-range integer, list selection, slice, and assignment. Assert both values and shape, because a scalar, Series, and DataFrame can contain similar data while supporting different downstream operations.

The official DataFrame.iloc reference defines positional selection. Compare it with the DataFrame.loc reference for label-based access. Related guidance includes DataFrame basics and testing patterns.

For related DataFrame selection, compare DataFrame structure, data export, and shape-focused tests before changing an indexing expression.

Frequently Asked Questions

What does iloc mean in pandas?

iloc is pandas’ integer-location indexer for selecting rows and columns by zero-based integer position rather than by label.

What is the difference between iloc and loc?

iloc selects by integer position, while loc selects by index or column labels and follows label-based slicing rules.

How do I select rows and columns with iloc?

Use df.iloc[row_selector, column_selector], where each selector can be an integer, slice, list of positions, or supported boolean array.

Why does pandas iloc raise an index error?

A requested integer position is outside the available range, or the selector shape and type do not match the DataFrame being indexed.

Subscribe
Notify of
guest
0 Comments
Oldest
Newest Most Voted