Pandas iloc: Select and Update Rows and Columns by Position

df.iloc[row_positions, column_positions] selects data by zero-based integer position. It is useful for inspecting imported files, taking slices and editing known positions. Use square brackets, not iloc(). A row label that looks like an integer is still a label: iloc always follows the current order.

Start with the student dataset to learn row and column selection, then inspect a sales extract and practise updating values. Each example includes its expected output so you can check your results.

Pandas iloc to get rows based on integer position using callback functions and array from DataFrame

Watch the video for a demonstration of positional selection, then try the examples below with Boolean arrays and callable selectors.

Create the Sample Student DataFrame

The four columns are NAME, ID, MATH and ENGLISH, at positions 0, 1, 2 and 3. Row positions run from 0 through 5. Use this small dataset to predict each selection. The larger student dataset provides more practice after these examples.

import pandas as pd

def student_data():
    return pd.DataFrame({
        "NAME": ["Ravi", "Raju", "Alex", "Ron", "King", "Jack"],
        "ID": [1, 2, 3, 4, 5, 6],
        "MATH": [30, 40, 50, 60, 70, 80],
        "ENGLISH": [20, 30, 40, 50, 60, 70]
    })

df = student_data()
print(df)

Expected output

   NAME  ID  MATH  ENGLISH
0  Ravi   1    30       20
1  Raju   2    40       30
2  Alex   3    50       40
3   Ron   4    60       50
4  King   5    70       60
5  Jack   6    80       70

Select the First and Second Rows

Use square brackets: iloc is an indexer, not a function call. A single integer selects one row and returns a Series. Its name is the original row label. Position 1 means the second row, regardless of the index labels.

df = student_data()
print("First row:")
print(df.iloc[0])
print("Second row:")
print(df.iloc[1])

Expected output

First row:
NAME       Ravi
ID            1
MATH         30
ENGLISH      20
Name: 0, dtype: object
Second row:
NAME       Raju
ID            2
MATH         40
ENGLISH      30
Name: 1, dtype: object

Keep a One-Row DataFrame

A list of positions preserves the two-dimensional DataFrame shape. This matters when a later operation expects column names and a table, rather than a Series. Compare iloc[0] and iloc[[0]] before exporting or joining a selection.

df = student_data()
print(df.iloc[[0]])
print(type(df.iloc[0]).__name__)
print(type(df.iloc[[0]]).__name__)

Expected output

   NAME  ID  MATH  ENGLISH
0  Ravi   1    30       20
Series
DataFrame

Read One Value by Row and Column Position

The first coordinate is the row, the second is the column. iloc[1, 2] reads Raju's MATH score, 40. Keep track of the column order; moving a column changes its position.

df = student_data()
print(df.iloc[1, 2])
print(df.iloc[1, 3])
assert df.iloc[1, 2] == 40

Expected output

40
30

Select the Last Row and Last Two Rows

Negative positions count backwards from the end. -1 is the last row; -2 is the second-last. A slice such as -2: returns a DataFrame. For a simple preview you can also use tail().

df = student_data()
print("Last row:")
print(df.iloc[-1])
print("Last MATH score:")
print(df.iloc[-1, 2])
print("Second-last row:")
print(df.iloc[-2])
print("Last two rows:")
print(df.iloc[-2:])

Expected output

Last row:
NAME       Jack
ID            6
MATH         80
ENGLISH      70
Name: 5, dtype: object
Last MATH score:
80
Second-last row:
NAME       King
ID            5
MATH         70
ENGLISH      60
Name: 4, dtype: object
Last two rows:
   NAME  ID  MATH  ENGLISH
4  King   5    70       60
5  Jack   6    80       70

Slice Rows: The Stop Position Is Excluded

iloc[2:5] returns positions 2, 3 and 4: Alex, Ron and King. The stop position 5 is excluded. Leaving the start blank begins at 0. Leaving the stop blank continues to the end. Compare head() for a quick first-rows preview.

df = student_data()
print("First two rows:")
print(df.iloc[:2])
print("Positions 2 through 4:")
print(df.iloc[2:5])
print("All except the last two:")
print(df.iloc[:-2])

Expected output

First two rows:
   NAME  ID  MATH  ENGLISH
0  Ravi   1    30       20
1  Raju   2    40       30
Positions 2 through 4:
   NAME  ID  MATH  ENGLISH
2  Alex   3    50       40
3   Ron   4    60       50
4  King   5    70       60
All except the last two:
   NAME  ID  MATH  ENGLISH
0  Ravi   1    30       20
1  Raju   2    40       30
2  Alex   3    50       40
3   Ron   4    60       50

Select First, Last and Reordered Rows

A list selects exactly the positions you request, in the requested order. It can repeat a position. Use this for a small inspection sample; it is not a random sample and may miss problems elsewhere in the dataset.

df = student_data()
print("First and last:")
print(df.iloc[[0, -1]])
print("A reordered sample:")
print(df.iloc[[4, 0, 2]])

Expected output

First and last:
   NAME  ID  MATH  ENGLISH
0  Ravi   1    30       20
5  Jack   6    80       70
A reordered sample:
   NAME  ID  MATH  ENGLISH
4  King   5    70       60
0  Ravi   1    30       20
2  Alex   3    50       40

Select Rows and Columns Together

A colon selects every position on that axis. df.iloc[:, 2] returns the MATH column as a Series. A list of column positions keeps a DataFrame. Column positions are zero-based, just like row positions.

df = student_data()
print("All rows and columns:")
print(df.iloc[::])
assert df.iloc[::].equals(df.iloc[:, :])
print("MATH as a Series:")
print(df.iloc[:, 2])
print("Two rows, NAME and MATH:")
print(df.iloc[:2, [0, 2]])

Expected output

All rows and columns:
   NAME  ID  MATH  ENGLISH
0  Ravi   1    30       20
1  Raju   2    40       30
2  Alex   3    50       40
3   Ron   4    60       50
4  King   5    70       60
5  Jack   6    80       70
MATH as a Series:
0    30
1    40
2    50
3    60
4    70
5    80
Name: MATH, dtype: int64
Two rows, NAME and MATH:
   NAME  MATH
0  Ravi    30
1  Raju    40

Select Alternate Rows and Reverse the Order

The third slice component is the step. ::2 selects positions 0, 2 and 4; ::3 selects 0 and 3. A negative step reverses the rows. This samples by current position, not by an ID value or a calendar interval.

df = student_data()
print("Every second row:")
print(df.iloc[::2])
print("Every third row:")
print(df.iloc[::3])
print("Reversed rows:")
print(df.iloc[::-1])

Expected output

Every second row:
   NAME  ID  MATH  ENGLISH
0  Ravi   1    30       20
2  Alex   3    50       40
4  King   5    70       60
Every third row:
   NAME  ID  MATH  ENGLISH
0  Ravi   1    30       20
3   Ron   4    60       50
Reversed rows:
   NAME  ID  MATH  ENGLISH
5  Jack   6    80       70
4  King   5    70       60
3   Ron   4    60       50
2  Alex   3    50       40
1  Raju   2    40       30
0  Ravi   1    30       20

Create an Empty Table with the Same Columns

The :0 slice returns no rows while preserving columns and dtypes. This is useful when preparing a schema for a later operation. It does not provide a new dataset with observations.

df = student_data()
empty = df.iloc[:0].copy()
print(empty)
assert empty.columns.tolist() == df.columns.tolist()
assert empty.dtypes.equals(df.dtypes)

Expected output

Empty DataFrame
Columns: [NAME, ID, MATH, ENGLISH]
Index: []

iloc vs loc When the Index Has Custom Labels

loc selects by labels; iloc selects by current order. Here label 0 does not exist, but position 0 still selects Ravi. loc label slices include the stop label when slicing this ordered index; iloc position slices exclude the stop position. See set_index() for choosing labels.

df = student_data()
df.index = [101, 205, 309, 412, 518, 623]
print("Position 0:")
print(df.iloc[[0]])
print("Label 205:")
print(df.loc[[205]])
print("Two positions:")
print(df.iloc[0:2])
print("Labels 101 through 309, inclusive:")
print(df.loc[101:309])

Expected output

Position 0:
     NAME  ID  MATH  ENGLISH
101  Ravi   1    30       20
Label 205:
     NAME  ID  MATH  ENGLISH
205  Raju   2    40       30
Two positions:
     NAME  ID  MATH  ENGLISH
101  Ravi   1    30       20
205  Raju   2    40       30
Labels 101 through 309, inclusive:
     NAME  ID  MATH  ENGLISH
101  Ravi   1    30       20
205  Raju   2    40       30
309  Alex   3    50       40

Use Boolean Arrays with the Correct Length

A row mask needs one True/False value per row; a column mask needs one per column. iloc uses the mask in positional order. The sample has four columns, so its column mask contains four Boolean values.

df = student_data()
print("NAME and MATH columns:")
print(df.iloc[:, [True, False, True, False]])
df2 = df.iloc[:3]
print("First and third of the three selected rows:")
print(df2.iloc[[True, False, True]])

Expected output

NAME and MATH columns:
   NAME  MATH
0  Ravi    30
1  Raju    40
2  Alex    50
3   Ron    60
4  King    70
5  Jack    80
First and third of the three selected rows:
   NAME  ID  MATH  ENGLISH
0  Ravi   1    30       20
2  Alex   3    50       40

Filter by a Condition: Convert the Mask for iloc

A comparison returns a Boolean Series. For iloc, pass a positional Boolean array with to_numpy(). For label-aware selection, loc accepts the Series directly. Build the mask from the same current DataFrame, especially after filtering or sorting.

df = student_data()
mask = df["MATH"].ge(50)
print(df.iloc[mask.to_numpy()])
assert df.iloc[mask.to_numpy()].equals(df.loc[mask])
assert df.loc[mask].equals(df[df["MATH"] >= 50])

Expected output

   NAME  ID  MATH  ENGLISH
2  Alex   3    50       40
3   Ron   4    60       50
4  King   5    70       60
5  Jack   6    80       70

Use Callable Selectors in a Method Chain

The callable receives the current DataFrame and returns positions or a Boolean array. This example includes alternate positions, selected positions, even student IDs and scores above a threshold. Positions [1, 3, 5] select the second, fourth and sixth rows of this dataset. Avoid a single callable returning a tuple; use separate row and column selectors.

df = student_data()
print("Alternate positions:")
print(df.iloc[lambda x: list(range(0, len(x), 2))])
print("Selected positions:")
print(df.iloc[lambda x: [1, 3, 5], :])
print("Even IDs:")
print(df.iloc[lambda x: x["ID"].mod(2).eq(0).to_numpy()])
print("MATH greater than 60:")
print(df.iloc[lambda x: x["MATH"].gt(60).to_numpy(), :])

Expected output

Alternate positions:
   NAME  ID  MATH  ENGLISH
0  Ravi   1    30       20
2  Alex   3    50       40
4  King   5    70       60
Selected positions:
   NAME  ID  MATH  ENGLISH
1  Raju   2    40       30
3   Ron   4    60       50
5  Jack   6    80       70
Even IDs:
   NAME  ID  MATH  ENGLISH
1  Raju   2    40       30
3   Ron   4    60       50
5  Jack   6    80       70
MATH greater than 60:
   NAME  ID  MATH  ENGLISH
4  King   5    70       60
5  Jack   6    80       70

Handle Out-of-Bounds Positions and Empty Tables

A single invalid position raises IndexError. A slice may extend beyond the end and simply return available rows. Check empty before asking for the first or last row when a filter may return no matches.

df = student_data()
try:
    df.iloc[6]
except IndexError:
    print("Position 6 is outside this six-row DataFrame.")
print("A slice safely stops at the end:")
print(df.iloc[4:20])
matches = df.loc[df["MATH"] > 100]
if matches.empty:
    print("No matching students; there is no last row to select.")

Expected output

Position 6 is outside this six-row DataFrame.
A slice safely stops at the end:
   NAME  ID  MATH  ENGLISH
4  King   5    70       60
5  Jack   6    80       70
No matching students; there is no last row to select.

Update One Cell and an Entire Column

Assign directly to the source DataFrame in one indexing operation. get_loc finds the current position of a named column; it assumes column names are unique. Position 3 is the fourth row, not necessarily label 3. For one scalar, iat is another positional option.

df = student_data()
math_position = df.columns.get_loc("MATH")
df.iloc[3, math_position] = 100
print(df)
assert df.iloc[3, math_position] == 100

df = student_data()
df.iloc[:, df.columns.get_loc("MATH")] = 100
print("All MATH scores updated:")
print(df)

Expected output

   NAME  ID  MATH  ENGLISH
0  Ravi   1    30       20
1  Raju   2    40       30
2  Alex   3    50       40
3   Ron   4   100       50
4  King   5    70       60
5  Jack   6    80       70
All MATH scores updated:
   NAME  ID  MATH  ENGLISH
0  Ravi   1   100       20
1  Raju   2   100       30
2  Alex   3   100       40
3   Ron   4   100       50
4  King   5   100       60
5  Jack   6   100       70

Update Matching Scores and Names

Convert a Boolean condition to a positional array before using it with iloc. The examples start from fresh data: set qualifying scores to 100, then replace a matching name. Prefer loc if your task is naturally expressed with column labels.

df = student_data()
mask = df["MATH"].ge(70).to_numpy()
df.iloc[mask, df.columns.get_loc("MATH")] = 100
print(df)
assert df["MATH"].tolist() == [30, 40, 50, 60, 100, 100]

df = student_data()
name_mask = df["NAME"].eq("Raju").to_numpy()
df.iloc[name_mask, df.columns.get_loc("NAME")] = "Updated name"
print(df.iloc[[1]])

Expected output

   NAME  ID  MATH  ENGLISH
0  Ravi   1    30       20
1  Raju   2    40       30
2  Alex   3    50       40
3   Ron   4    60       50
4  King   5   100       60
5  Jack   6   100       70
           NAME  ID  MATH  ENGLISH
1  Updated name   2    40       30

Update with a Loop Without Confusing Labels and Positions

If a loop is necessary, iterate over range(len(df)), not df.index. Index labels can be strings or nonconsecutive integers. The direct whole-column assignment shown afterwards is clearer when every row receives the same value.

df = student_data()
df.index = [101, 205, 309, 412, 518, 623]
for position in range(len(df)):
    df.iloc[position, 3] = 51
print(df)

direct = student_data()
direct.iloc[:, 3] = 51
assert df["ENGLISH"].tolist() == direct["ENGLISH"].tolist()

Expected output

     NAME  ID  MATH  ENGLISH
101  Ravi   1    30       51
205  Raju   2    40       51
309  Alex   3    50       51
412   Ron   4    60       51
518  King   5    70       51
623  Jack   6    80       51

Practical Workflow: Inspect a Sales Extract After Sorting

Position is a property of the current row order. This synthetic sales extract has IDs and amounts that deliberately arrive out of order. Sort by amount, then select the first three rows and the columns required for a review. In an actual import, inspect column names before using positional column selections.

sales = pd.DataFrame({
    "order_id": [1004, 1001, 1005, 1002, 1003],
    "customer": ["Office A", "Shop B", "Office C", "Shop D", "Office E"],
    "amount": [80, 250, 120, 40, 175]
})
ranked = sales.sort_values("amount", ascending=False)
review = ranked.iloc[:3, [0, 2]].copy()
print(review)
assert review["order_id"].tolist() == [1001, 1003, 1005]
print("Current first-row label:", ranked.index[0])
print("Current first-row order:", ranked.iloc[0, 0])

Expected output

   order_id  amount
1      1001     250
4      1003     175
2      1005     120
Current first-row label: 1
Current first-row order: 1001

Edit an Independent Selection Deliberately

Use copy() when you want a separate review table. Updating that review table should not update the original source. To change the source itself, assign directly to it with iloc or loc. Avoid chained assignments such as df.iloc[:2]["MATH"] = 0.

df = student_data()
review = df.iloc[:2].copy()
review.iloc[:, review.columns.get_loc("MATH")] = 0
print("Edited review:")
print(review)
print("Original scores:", df["MATH"].tolist())
assert df["MATH"].tolist() == [30, 40, 50, 60, 70, 80]

Expected output

Edited review:
   NAME  ID  MATH  ENGLISH
0  Ravi   1     0       20
1  Raju   2     0       30
Original scores: [30, 40, 50, 60, 70, 80]

Exercise: Select and Verify a Small Report

Select every second student starting at position 1, with only NAME and ENGLISH. Predict the names and values first. Then verify the shape is three rows by two columns. Expected names: Raju, Ron and Jack; scores: 30, 50 and 70.

Exercise Solution

The slice 1::2 starts at the second row and advances two positions at a time. The column list [0, 3] selects NAME and ENGLISH while preserving a DataFrame.

df = student_data()
answer = df.iloc[1::2, [0, 3]]
print(answer)
assert answer.shape == (3, 2)
assert answer["NAME"].tolist() == ["Raju", "Ron", "Jack"]
assert answer["ENGLISH"].tolist() == [30, 50, 70]

Expected output

   NAME  ENGLISH
1  Raju       30
3   Ron       50
5  Jack       70

Quick Selection Reference

Return to these examples when choosing the output shape. The comments identify positions using the actual sample column order. Each expression below is valid for the six-row student dataset.

df = student_data()
print(df.iloc[::])          # All rows
print(df.iloc[0])           # First row as Series
print(df.iloc[1])           # Second row as Series
print(df.iloc[1, 3])        # Second row, fourth column: ENGLISH = 30
print(df.iloc[:, 1])        # ID column as Series
print(df.iloc[-1])          # Last row as Series
print(df.iloc[[-1]])        # Last row as DataFrame
print(df.iloc[:2])          # First two rows
print(df.iloc[:-2])         # All except the last two
print(df.iloc[-2])          # Second-last row
print(df.iloc[-2:])         # Last two rows
print(df.iloc[2:5])         # Positions 2, 3 and 4
print(df.iloc[[0, -1]])     # First and last
print(df.iloc[::2])         # Positions 0, 2 and 4
print(df.iloc[::3])         # Positions 0 and 3

Expected output

   NAME  ID  MATH  ENGLISH
0  Ravi   1    30       20
1  Raju   2    40       30
2  Alex   3    50       40
3   Ron   4    60       50
4  King   5    70       60
5  Jack   6    80       70
NAME       Ravi
ID            1
MATH         30
ENGLISH      20
Name: 0, dtype: object
NAME       Raju
ID            2
MATH         40
ENGLISH      30
Name: 1, dtype: object
30
0    1
1    2
2    3
3    4
4    5
5    6
Name: ID, dtype: int64
NAME       Jack
ID            6
MATH         80
ENGLISH      70
Name: 5, dtype: object
   NAME  ID  MATH  ENGLISH
5  Jack   6    80       70
   NAME  ID  MATH  ENGLISH
0  Ravi   1    30       20
1  Raju   2    40       30
   NAME  ID  MATH  ENGLISH
0  Ravi   1    30       20
1  Raju   2    40       30
2  Alex   3    50       40
3   Ron   4    60       50
NAME       King
ID            5
MATH         70
ENGLISH      60
Name: 4, dtype: object
   NAME  ID  MATH  ENGLISH
4  King   5    70       60
5  Jack   6    80       70
   NAME  ID  MATH  ENGLISH
2  Alex   3    50       40
3   Ron   4    60       50
4  King   5    70       60
   NAME  ID  MATH  ENGLISH
0  Ravi   1    30       20
5  Jack   6    80       70
   NAME  ID  MATH  ENGLISH
0  Ravi   1    30       20
2  Alex   3    50       40
4  King   5    70       60
   NAME  ID  MATH  ENGLISH
0  Ravi   1    30       20
3   Ron   4    60       50

Choose the Right Selection Tool

Use loc when labels or aligned conditions express your intent. Use head() and tail() for previews. Use reset_index() when you intentionally want to change the labels; it is not required for iloc. Explore DataFrame attributes to learn about indexers and other table properties. For array slicing, compare NumPy indexing and slicing.

Practice in Google Colab

Open in Google Colab View on GitHub
All sample data is embedded. Run the cells in order, change positions and compare Series versus DataFrame outputs.

Reference: Pandas DataFrame.iloc documentation.




Subscribe to our YouTube Channel here



plus2net.com







Python Video Tutorials
Python SQLite Video Tutorials
Python MySQL Video Tutorials
Python Tkinter Video Tutorials
✖
We use cookies to improve your browsing experience. . Learn more
HTML MySQL PHP JavaScript ASP Photoshop Articles Contact us
© 2000-2026 plus2net.com All rights reserved worldwide Privacy Policy Disclaimer