Skip to content

Python NumPy: How to Get the Index of a NumPy Multidimensional Array in Reverse Order in Python

Learn how to find the last occurrence of an element in each row of a NumPy array by flipping rows and using np.argmax() for reverse-order indexing.

When working with NumPy multidimensional arrays, you may need to find the last occurrence of a specific element in each row, i.e. essentially searching from right to left. NumPy's built-in search functions like np.where() and np.argmax() search left to right by default, so finding elements in reverse requires a different approach.

In this guide, we'll show you how to search arrays in reverse order and return the correct indices.

The Problem

Consider this array where you want to find the last occurrence of the value 2 in each row:

import numpy as np

arr = np.array([
    [1, 2, 3, 4, 2],
    [2, 3, 4, 1, 5],
    [2, 2, 4, 3, 2],
    [1, 3, 4, 2, 4]
])
  • Row 0: [1, 2, 3, 4, 2] → last 2 is at index 4
  • Row 1: [2, 3, 4, 1, 5] → last 2 is at index 0
  • Row 2: [2, 2, 4, 3, 2] → last 2 is at index 4
  • Row 3: [1, 3, 4, 2, 4] → last 2 is at index 3

Expected result: [4, 0, 4, 3]

The Approach

The strategy is straightforward:

  1. Flip each row (or the entire array along the column axis).
  2. Find the index of the first occurrence in the flipped row.
  3. Convert the reversed index back to the original index using the formula:
original_index = number_of_columns - reversed_index - 1

Method 1: Using a Loop with np.flip() and np.where()

This approach processes each row individually - clear and easy to understand:

import numpy as np

arr = np.array([
    [1, 2, 3, 4, 2],
    [2, 3, 4, 1, 5],
    [2, 2, 4, 3, 2],
    [1, 3, 4, 2, 4]
])

target = 2
num_cols = arr.shape[1]
reversed_indices = []

for row in arr:
    flipped = np.flip(row)
    index = np.where(flipped == target)[0][0]  # First match in reversed row
    reversed_indices.append(index)

result = num_cols - np.array(reversed_indices) - 1
print(f"Last occurrence of {target} in each row: {result}")

Output:

Last occurrence of 2 in each row: [4 0 4 3]

How the Index Conversion Works

Let's trace through Row 2 ([2, 2, 4, 3, 2]):

Original:  [2, 2, 4, 3, 2]   (indices: 0, 1, 2, 3, 4)
Flipped:   [2, 3, 4, 2, 2]   (indices: 0, 1, 2, 3, 4)

First '2' in flipped row is at index 0.
Original index = 5 - 0 - 1 = 4  ✅ (Correct: the last '2' is at position 4)

Method 2: Vectorized Approach (No Loops)

For better performance on large arrays, avoid loops entirely by flipping the whole array at once:

import numpy as np

arr = np.array([
    [1, 2, 3, 4, 2],
    [2, 3, 4, 1, 5],
    [2, 2, 4, 3, 2],
    [1, 3, 4, 2, 4]
])

target = 2
num_cols = arr.shape[1]

flipped = arr[:, ::-1]

mask = (flipped == target)
reversed_indices = np.argmax(mask, axis=1)

result = num_cols - reversed_indices - 1
print(f"Last occurrence of {target} in each row: {result}")

Output:

Last occurrence of 2 in each row: [4 0 4 3]

Method 3: Working with String Arrays

The same approach works with string data:

import numpy as np

arr = np.array([
    ["Sam", "John", "Lilly"],
    ["Sam", "Sam",  "Kate"],
    ["Jack", "John", "Sam"],
    ["Sam", "Jack", "Rose"]
])

target = "Sam"
num_cols = arr.shape[1]

flipped = arr[:, ::-1]
mask = (flipped == target)
reversed_indices = np.argmax(mask, axis=1)

exists = np.any(mask, axis=1)
result = np.where(exists, num_cols - reversed_indices - 1, -1)

print(f"Last occurrence of '{target}' in each row: {result}")

Output:

Last occurrence of 'Sam' in each row: [0 1 2 0]

Method 4: Working with Boolean Arrays

For boolean arrays, finding the last True value is even simpler because True equals 1 - the maximum value. You can use np.argmax() directly:

import numpy as np

arr = np.array([
    [True,  False, True,  True],
    [False, False, True,  False],
    [False, True,  True,  True],
    [True,  False, False, True]
])

num_cols = arr.shape[1]

flipped = arr[:, ::-1]
reversed_indices = np.argmax(flipped, axis=1)
result = num_cols - reversed_indices - 1

print(f"Last True in each row: {result}")

Output:

Last True in each row: [3 2 3 3]

Complete Reusable Function

Here's a function that handles all the edge cases:

import numpy as np

def find_last_occurrence(arr, target):
    """
    Find the index of the last occurrence of `target` in each row
    of a 2D NumPy array.

    Returns -1 for rows where the target is not found.
    """
    if arr.ndim != 2:
        raise ValueError("Input array must be 2-dimensional.")

    num_cols = arr.shape[1]

    flipped = arr[:, ::-1]
    mask = (flipped == target)

    exists = np.any(mask, axis=1)

    reversed_indices = np.argmax(mask, axis=1)

    result = np.where(exists, num_cols - reversed_indices - 1, -1)

    return result


arr = np.array([
    [1, 2, 3, 4, 2],
    [2, 3, 4, 1, 5],
    [2, 2, 4, 3, 2],
    [1, 3, 4, 7, 4]   # No '2' in this row
])

result = find_last_occurrence(arr, 2)
print(f"Last occurrence of 2: {result}")

result = find_last_occurrence(arr, 4)
print(f"Last occurrence of 4: {result}")

Output:

Last occurrence of 2: [ 4  0  4 -1]
Last occurrence of 4: [3 2 2 4]

Finding First vs Last Occurrence - Comparison

Goal Method
First occurrence (left to right) np.argmax(arr == target, axis=1)
Last occurrence (right to left) Flip → argmax → convert index
All occurrences np.where(arr == target)
import numpy as np

arr = np.array([
    [2, 3, 2, 4, 2],
    [1, 2, 3, 2, 5]
])

target = 2

first = np.argmax(arr == target, axis=1)
print(f"First: {first}")  # [0 1]

flipped = arr[:, ::-1]
last = arr.shape[1] - np.argmax(flipped == target, axis=1) - 1
print(f"Last:  {last}")   # [4 3]

Output:

First: [0 1]
Last:  [4 3]

Conclusion

To find element indices in a NumPy multidimensional array in reverse order (i.e., the last occurrence in each row), flip the array along the column axis using arr[:, ::-1], find the first match with np.argmax(), and convert back to the original index with the formula original = num_cols - reversed_index - 1.

The vectorized approach using slicing and np.argmax() is both concise and performant, working efficiently on large arrays.

Always add an existence check with np.any() to handle rows where the target value doesn't appear.

Navigation