Python NumPy: How to Get the Index of a NumPy Multidimensional Array in Reverse Order in Python
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 - 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)
# Convert reversed indices to original indices
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]
# Flip all rows at once (reverse column order)
flipped = arr[:, ::-1]
# Find first occurrence in each row of flipped array
# Create a boolean mask and use argmax (True=1 is the "max")
mask = (flipped == target)
reversed_indices = np.argmax(mask, axis=1)
# Convert to original indices
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]
The vectorized approach using arr[:, ::-1] and np.argmax() is significantly faster than the loop-based approach for large arrays because it leverages NumPy's optimized C operations.
np.argmax() returns 0 when no True value exists in a row (since all values are False/0 and it picks the first). This means if the target value doesn't exist in a row, you'll get an incorrect result. Add a check:
# Check if target exists in each row
exists = np.any(mask, axis=1)
result = np.where(exists, num_cols - reversed_indices - 1, -1)
print(result) # -1 indicates "not found"
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)
# Check existence
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]
# Flip and find first True (which is the last True in original)
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]
# Flip columns and find first occurrence
flipped = arr[:, ::-1]
mask = (flipped == target)
# Check if target exists in each row
exists = np.any(mask, axis=1)
# Get reversed indices (argmax returns 0 if no match, handle with 'exists')
reversed_indices = np.argmax(mask, axis=1)
# Convert to original indices, use -1 for "not found"
result = np.where(exists, num_cols - reversed_indices - 1, -1)
return result
# Example usage
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 occurrence
first = np.argmax(arr == target, axis=1)
print(f"First: {first}") # [0 1]
# Last occurrence
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.