Fixed “Indexerror: single positional indexer is out-of-bounds”

Category: Programming, Python | August 9, 2023

The “IndexError: single positional indexer is out-of-bounds” is a common error encountered while working with pandas DataFrames in Python. It occurs when attempting to access elements using invalid row or column indices. In this article, we will explore the main causes of this error and provide practical solutions to fix it. Let’s dive in!

What is “IndexError: single positional indexer is out-of-bounds” error?

This is a specific type of IndexError that occurs when working with pandas DataFrames. It arises when attempting to access DataFrame elements using invalid integer-based indexers or using non-existent row or column indices. This error indicates that the index being used to access the DataFrame is either out of the valid range or does not exist in the DataFrame.

How is this error different from other IndexError errors?

While “IndexError: single positional indexer is out-of-bounds” is a subtype of the generic IndexError, it has unique characteristics. Unlike other IndexError errors, which may occur when working with lists, arrays, or sequences, this error is specific to pandas DataFrames. It typically arises when using incorrect indexing methods like iloc or iat with non-existent or out-of-bounds indices.

What causes the error in Python?

This error is specific to DataFrame indexing methods, such as ilociatloc and at. Let’s explore several common scenarios that trigger this error and understand the root causes behind each one.

DataFrame Indexing Functions:

  • iloc: Used for integer-based indexing, allowing us to access DataFrame elements using numeric row and column indices.
  • iat: A faster version of iloc for scalar (single element) access, where we can provide numeric row and column indices to retrieve a single cell’s value.
  • loc: Used for label-based indexing, allowing us to access DataFrame elements using row and column labels (index names) instead of numeric indices.
  • at: A faster version of loc for scalar access, where we can provide row and column labels to retrieve a single cell’s value.

Also, for every scenario in this article, we will use the small data set below to demonstrate our examples:

data set

Notice that this DataFrame has 3 columns and 4 rows.

Scenario 1: Invalid Row Index

invalid row index

In this scenario, the error occurs when trying to access a row in the DataFrame using an invalid row index. For instance, we attempt to access the 5th row in the data set using iloc:

import pandas as pd

# The data set is stored in data
data = {'Name': ['John', 'Jane', 'Mike', 'Alice'],
        'Age': [25, 30, 22, 28],
        'City': ['New York', 'San Francisco', 'Chicago', 'Los Angeles']}

df = pd.DataFrame(data)

# Invalid row index access
print(df.iloc[4])  # Attempting to access the 5th row

This occurs because the DataFrame only has four rows with valid indices 0 to 3, and attempting to access the 5th row (index 4) leads to the “IndexError”.

Note: Python indexes are zero-based, so the index of the first column is 0 and the index of the last column is -1. And it’s totally fine to use negative indexes for accessing the data, as long as they are integers.

Scenario 2: Invalid Column Index

invalid column index

The same error arises when trying to access a column in the DataFrame using an invalid column index. This time we attempt to access the 4th column (index 3) in a DataFrame with three columns:

import pandas as pd

data = {'Name': ['John', 'Jane', 'Mike', 'Alice'],
        'Age': [25, 30, 22, 28],
        'City': ['New York', 'San Francisco', 'Chicago', 'Los Angeles']}

df = pd.DataFrame(data)

# Invalid column index access
print(df.iloc[:, 3])  # Attempting to access the 4th column

Again, this occurs because the DataFrame has only three columns with valid indices 0 to 2, and we are attempting to access the 4th column (index 3).

How to fix this problem?

Knowing the causes of the error is the first step to solving it. After that, you can follow these steps to resolve the issue:

Step 1: Verify DataFrame’s Number of Rows and Columns

Before accessing elements using iloc, ensure you know the number of rows in your DataFrame. You can use the shape attribute to obtain the dimensions of the DataFrame.

# Get the number of rows and columns in DataFrame
num_rows = df.shape[0]
num_columns = df.shape[1]
print("Number of rows: ", num_rows, "\nNumber of columns: ", num_columns)

Step 2: Ensure the Index is Within Bounds

You should make sure to verify that the index falls within the valid range (0 to num - 1). Use conditional statements to check the index before accessing the row or column.

num_rows = df.shape[0]
row_index = 4  # The row index to access

if row_index >= 0 and row_index < num_rows:
    print(df.iloc[row_index])
else:
    print("Invalid row index. Index should be between 0 and", num_rows - 1)

Step 3: Avoid Hardcoding Indices

Instead of hardcoding row indices, use loop constructs or iterators to iterate over the DataFrame rows. This prevents the need to access specific rows by index.

# Loop all rows
for index, row in df.iterrows():
    print("Row", index, ":", row)

Step 4: Handle Potential Exceptions

To avoid the “IndexError” altogether, consider using exception handling when working with user-provided or uncertain data. Use try-except blocks to catch and handle potential exceptions.

try:
    print(df.iloc[5]) # Attempting to access the 6th row
except IndexError:
    print("Invalid row index. Please ensure the index is within the valid range.")

Some tips to avoid this error

Use CSV Reading with Error Handling

When reading data from CSV files, use Python’s built-in file handling and error handling mechanisms to check if the file is empty or does not exist before attempting to create a DataFrame.

import pandas as pd

file_path = 'data.csv'
try:
    with open(file_path) as f:
        first_line = f.readline()
        if not first_line:
            print("File is empty!")
        else:
            df = pd.read_csv(file_path)
except FileNotFoundError:
    print("File not found!")

Consider alternatives to DataFrames

While pandas DataFrames are a powerful tool for data manipulation and analysis, there are instances where you might prefer alternatives to avoid potential errors like “IndexError: single positional indexer is out-of-bounds.”

Use Dictionaries or NamedTuples

If you need labeled data and a DataFrame is not necessary, consider using dictionaries or collections.namedtuple. These data structures can provide similar functionality without the overhead of a DataFrame.

# Use dictionaries
data = [{'Name': 'John', 'Age': 25, 'City': 'New York'},
        {'Name': 'Jane', 'Age': 30, 'City': 'San Francisco'},
        {'Name': 'Mike', 'Age': 22, 'City': 'Chicago'},
        {'Name': 'Alice', 'Age': 28, 'City': 'Los Angeles'}]
        
# Use NamedTuples
from collections import namedtuple

Person = namedtuple('Person', ['Name', 'Age', 'City'])
data = [Person('John', 25, 'New York'),
        Person('Jane', 30, 'San Francisco'),
        Person('Mike', 22, 'Chicago'),
        Person('Alice', 28, 'Los Angeles')]

For Simple Lists

For simple operations on lists or arrays, use native Python lists or NumPy arrays. DataFrame overhead might not be necessary, and it reduces the risk of DataFrame-related errors.

# Use native Python lists
data = [1, 2, 3, 4, 5]
mean_value = sum(data) / len(data)

# Or NumPy arrays
import numpy as np

data = np.array([1, 2, 3, 4, 5])
mean_value = np.mean(data)

Conclusion

The “IndexError: single positional indexer is out-of-bounds” error is a specific type of IndexError that occurs when accessing elements in pandas DataFrames using invalid indices. This error can arise due to various scenarios, such as invalid row or column indices with ilociatloc, and at. By understanding these scenarios and the functions’ behavior, we can effectively troubleshoot and resolve the errors. To avoid encountering this error, it is essential to verify DataFrame dimensions, use valid indices and labels, and handle potential exceptions gracefully. Additionally, employing loop constructs for safer row access and being cautious when reading data from CSV files can prevent DataFrame-related issues. Implementing these best practices ensures smoother data manipulation and analysis with pandas, enhancing the overall reliability and efficiency of our Python programs.

That’s it for today. Have fun coding!