Skip to main content

Python Pandas: How to Get Nth Row or Every Nth Row from DataFrame

Selecting specific rows or a regular pattern of rows from a Pandas DataFrame based on their integer position is a common data access pattern. You might need to retrieve a single Nth row, or sample your data by selecting every Kth row. Pandas provides efficient integer-location based indexers like iloc and other methods to achieve this.

This guide explains how to get a specific Nth row and how to select every Nth row (with variations like starting at a specific row or using the modulo operator) from a Pandas DataFrame.

Understanding Positional Indexing

Pandas DataFrames have an index that labels the rows. By default, this is a RangeIndex starting from 0 (0, 1, 2, ...). "Positional indexing" refers to selecting rows based on these integer positions, regardless of what the actual index labels might be (e.g., if you have a custom string index). DataFrame.iloc is the primary tool for this.

Example DataFrame

import pandas as pd

data = {
'Student_ID': [f'S{1001+i}' for i in range(10)],
'Test_Score': [85, 92, 78, 95, 88, 72, 90, 81, 79, 93],
'Subject': ['Math', 'Science', 'Math', 'History', 'Science', 'Math', 'History', 'Science', 'Math', 'History']
}

df = pd.DataFrame(data)
print("Original DataFrame:")
print(df)

Output:

Original DataFrame:
Student_ID Test_Score Subject
0 S1001 85 Math
1 S1002 92 Science
2 S1003 78 Math
3 S1004 95 History
4 S1005 88 Science
5 S1006 72 Math
6 S1007 90 History
7 S1008 81 Science
8 S1009 79 Math
9 S1010 93 History

Get a SINGLE Nth Row

Remember that Pandas uses zero-based indexing, so the first row is at position 0, the second at position 1, and so on.

Using DataFrame.iloc[n] (Returns a Series)

Accessing a single row by its integer position using df.iloc[n] returns the row as a Pandas Series.

import pandas as pd

df = pd.DataFrame({
'Student_ID': [f'S{1001+i}' for i in range(10)],
'Test_Score': [85, 92, 78, 95, 88, 72, 90, 81, 79, 93],
'Subject': ['Math', 'Science', 'Math', 'History', 'Science', 'Math', 'History', 'Science', 'Math', 'History']
})

# Get the 3rd row (index 2) as a Series
third_row_series = df.iloc[2]

print("Third row (index 2) as a Series:")
print(third_row_series)

# Get the first row (index 0)
first_row_series = df.iloc[0]
print("First row (index 0) as a Series:")
print(first_row_series)

Output:

Third row (index 2) as a Series:
Student_ID S1003
Test_Score 78
Subject Math
Name: 2, dtype: object

First row (index 0) as a Series:
Student_ID S1001
Test_Score 85
Subject Math
Name: 0, dtype: object

Using DataFrame.iloc[[n]] (Returns a DataFrame)

If you want the Nth row returned as a single-row DataFrame (preserving the column structure), pass the index as a list: df.iloc[[n]].

import pandas as pd

df = pd.DataFrame({
'Student_ID': [f'S{1001+i}' for i in range(10)],
'Test_Score': [85, 92, 78, 95, 88, 72, 90, 81, 79, 93],
'Subject': ['Math', 'Science', 'Math', 'History', 'Science', 'Math', 'History', 'Science', 'Math', 'History']
})

# Get the 3rd row (index 2) as a DataFrame
third_row_df = df.iloc[[2]] # Note the double square brackets

print("Third row (index 2) as a DataFrame:")
print(third_row_df)

Output:

Third row (index 2) as a DataFrame:
Student_ID Test_Score Subject
2 S1003 78 Math

Using DataFrame.take([n]) (Returns a DataFrame)

The DataFrame.take() method can also be used to select rows by their integer positions. It expects a list-like of indices.

import pandas as pd

df = pd.DataFrame({
'Student_ID': [f'S{1001+i}' for i in range(10)],
'Test_Score': [85, 92, 78, 95, 88, 72, 90, 81, 79, 93],
'Subject': ['Math', 'Science', 'Math', 'History', 'Science', 'Math', 'History', 'Science', 'Math', 'History']
})

# Get the 4th row (index 3) as a DataFrame
fourth_row_take = df.take([3])

print("Fourth row (index 3) using .take():")
print(fourth_row_take)

Output:

Fourth row (index 3) using .take():
Student_ID Test_Score Subject
3 S1004 95 History

Get EVERY Nth Row

This is useful for sampling or selecting rows at regular intervals.

Using DataFrame.iloc[::N] (Slicing)

Python's slicing syntax start:stop:step can be used with iloc. To get every Nth row starting from the beginning: df.iloc[::N].

import pandas as pd

df = pd.DataFrame({
'Student_ID': [f'S{1001+i}' for i in range(10)],
'Test_Score': [85, 92, 78, 95, 88, 72, 90, 81, 79, 93],
'Subject': ['Math', 'Science', 'Math', 'History', 'Science', 'Math', 'History', 'Science', 'Math', 'History']
})

# Get every 3rd row (0, 3, 6, 9...)
every_3rd_row = df.iloc[::3]
# The ", :" part to select all columns is often optional for row-only slicing
# every_3rd_row = df.iloc[::3, :] # Explicitly all columns

print("Every 3rd row using iloc slicing (df.iloc[::3]):")
print(every_3rd_row)

Output:

Every 3rd row using iloc slicing (df.iloc[::3]):
Student_ID Test_Score Subject
0 S1001 85 Math
3 S1004 95 History
6 S1007 90 History
9 S1010 93 History

Starting at a Specific Row X, then Every Nth (df.iloc[X::N])

To start selection from a specific row position X and then take every Nth row:

import pandas as pd

df = pd.DataFrame({
'Student_ID': [f'S{1001+i}' for i in range(10)],
'Test_Score': [85, 92, 78, 95, 88, 72, 90, 81, 79, 93],
'Subject': ['Math', 'Science', 'Math', 'History', 'Science', 'Math', 'History', 'Science', 'Math', 'History']
})

# Get every 3rd row, starting from the 2nd row (index 1)
every_3rd_from_row1 = df.iloc[1::3]

print("Every 3rd row, starting from index 1 (df.iloc[1::3]):")
print(every_3rd_from_row1)

Output:

Every 3rd row, starting from index 1 (df.iloc[1::3]):
Student_ID Test_Score Subject
1 S1002 92 Science
4 S1005 88 Science
7 S1008 81 Science

Using the Modulo Operator (%) on the Index

This method works well if your DataFrame has a default RangeIndex (0, 1, 2, ...) or a numeric index where modulo makes sense.

import pandas as pd

df = pd.DataFrame({
'Student_ID': [f'S{1001+i}' for i in range(10)],
'Test_Score': [85, 92, 78, 95, 88, 72, 90, 81, 79, 93],
'Subject': ['Math', 'Science', 'Math', 'History', 'Science', 'Math', 'History', 'Science', 'Math', 'History']
})

# Get every 2nd row (rows where index % 2 == 0: 0, 2, 4, ...)
every_2nd_row_modulo = df[df.index % 2 == 0]

print("Every 2nd row using modulo operator (df.index % 2 == 0):")
print(every_2nd_row_modulo)
print()

# To get every 2nd row *starting from the second row* (indices 1, 3, 5...)
# (rows where index % 2 == 1)
every_2nd_row_odd_indices = df[df.index % 2 != 0] # Or == 1
print("Rows at odd indices using modulo (df.index % 2 != 0):")
print(every_2nd_row_odd_indices)

Output:

Every 2nd row using modulo operator (df.index % 2 == 0):
Student_ID Test_Score Subject
0 S1001 85 Math
2 S1003 78 Math
4 S1005 88 Science
6 S1007 90 History
8 S1009 79 Math

Rows at odd indices using modulo (df.index % 2 != 0):
Student_ID Test_Score Subject
1 S1002 92 Science
3 S1004 95 History
5 S1006 72 Math
7 S1008 81 Science
9 S1010 93 History
  • If your DataFrame has a non-numeric index or an index that doesn't start at 0 in a predictable way, you might need to reset_index() first to use this method reliably based on row position: df[df.reset_index().index % N == K] (where K is the remainder for the desired starting offset).

Exclude Every Nth Row

To get all rows except every Nth row, you can invert the condition used with the modulo operator.

import pandas as pd

df = pd.DataFrame({
'Student_ID': [f'S{1001+i}' for i in range(10)],
'Test_Score': [85, 92, 78, 95, 88, 72, 90, 81, 79, 93],
'Subject': ['Math', 'Science', 'Math', 'History', 'Science', 'Math', 'History', 'Science', 'Math', 'History']
})

# Exclude every 3rd row (i.e., keep rows where index % 3 is NOT 0)
# This keeps rows with index 1, 2, 4, 5, 7, 8...
exclude_every_3rd_row = df[df.index % 3 != 0]

print("Excluding every 3rd row (keeping rows where index % 3 != 0):")
print(exclude_every_3rd_row)

Output:

Excluding every 3rd row (keeping rows where index % 3 != 0):
Student_ID Test_Score Subject
1 S1002 92 Science
2 S1003 78 Math
4 S1005 88 Science
5 S1006 72 Math
7 S1008 81 Science
8 S1009 79 Math

Conclusion

Pandas offers flexible ways to select rows by their integer positions:

  • To get a single Nth row:
    • df.iloc[n] (returns a Series).
    • df.iloc[[n]] (returns a DataFrame).
    • df.take([n]) (returns a DataFrame).
  • To get every Nth row:
    • df.iloc[start::step] (slicing) is very powerful and concise.
    • df[df.index % N == K] (modulo operator) works well for DataFrames with a default or predictable numeric index.

Choose the method that best fits your specific selection criteria (single row, patterned selection, desired output type) and the nature of your DataFrame's index. iloc is generally the most versatile tool for positional indexing.