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]→ last2is at index 4 - Row 1:
[2, 3, 4, 1, 5]→ last2is at index 0 - Row 2:
[2, 2, 4, 3, 2]→ last2is at index 4 - Row 3:
[1, 3, 4, 2, 4]→ last2is at index 3
Expected result: [4, 0, 4, 3]
The Approach
The strategy is straightforward:
- Flip each row (or the entire array along the column axis).
- Find the index of the first occurrence in the flipped row.
- Convert the reversed index back to the original index using the formula:
original_index = number_of_columns - reversed_index - 1Method 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.