Python NumPy: How to Swap Two Rows in a NumPy Array
Swapping rows in a NumPy array is a common operation in data preprocessing, matrix manipulation, and algorithm implementation. Whether you need to reorder data for analysis, implement sorting algorithms, or rearrange matrices for linear algebra operations, NumPy provides several efficient ways to exchange rows.
This guide covers four practical methods with clear examples and outputs.
Sample Array
All examples use the following 2D NumPy array:
import numpy as np
arr = np.array([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
[10, 11, 12]
])
print(arr)
Output:
[[ 1 2 3]
[ 4 5 6]
[ 7 8 9]
[10 11 12]]
Method 1: Using Advanced Indexing (Recommended)
The most concise and Pythonic way to swap two rows is using NumPy's advanced indexing. Assign the rows in reversed order simultaneously:
import numpy as np
arr = np.array([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
[10, 11, 12]
])
# Swap row 0 and row 3
arr[[0, 3]] = arr[[3, 0]]
print(arr)
Output:
[[10 11 12]
[ 4 5 6]
[ 7 8 9]
[ 1 2 3]]
Rows 0 and 3 are swapped in a single line. This works because NumPy evaluates the right side first, then assigns both rows simultaneously.
This is the recommended method for swapping two specific rows. It is concise, efficient, and reads clearly as a swap operation.
Method 2: Using Fancy Indexing to Reorder Multiple Rows
If you need to rearrange multiple rows at once - not just swap two - specify the desired row order as a list of indices:
import numpy as np
arr = np.array([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
])
print("Original:")
print(arr)
# Reorder: move row 2 to position 0, row 0 to position 1, row 1 to position 2
reordered = arr[[2, 0, 1]]
print("\nReordered:")
print(reordered)
Output:
Original:
[[1 2 3]
[4 5 6]
[7 8 9]]
Reordered:
[[7 8 9]
[1 2 3]
[4 5 6]]
The index list [2, 0, 1] means: take row 2 first, then row 0, then row 1. This creates a new array - the original is unchanged.
Fancy indexing with a list (e.g., arr[[2, 0, 1]]) creates a copy of the data, while advanced indexing assignment (e.g., arr[[0, 3]] = arr[[3, 0]]) modifies the array in place.
Method 3: Using Direct Assignment with a Temporary Copy
This method mirrors the classic variable-swap pattern using a temporary variable. It's explicit and easy to understand:
import numpy as np
arr = np.array([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
])
print("Before swap:")
print(arr)
# Swap row 1 and row 2 using a temporary copy
temp = arr[1].copy()
arr[1] = arr[2]
arr[2] = temp
print("\nAfter swap:")
print(arr)
Output:
Before swap:
[[1 2 3]
[4 5 6]
[7 8 9]]
After swap:
[[1 2 3]
[7 8 9]
[4 5 6]]
Why .copy() Is Required
Without .copy(), the temporary variable temp would be a view of the original row, not an independent copy. When arr[1] is overwritten, temp would also change:
import numpy as np
arr = np.array([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
])
# WRONG: temp is a view, not a copy
temp = arr[1] # temp points to the same memory as arr[1]
arr[1] = arr[2] # This overwrites arr[1], which also changes temp!
arr[2] = temp # Now temp contains [7, 8, 9] (the overwritten value)
print(arr)
Output:
[[1 2 3]
[7 8 9]
[7 8 9]]
Both rows end up with the same values - the swap fails silently.
The correct approach:
# CORRECT: temp is an independent copy
temp = arr[1].copy()
arr[1] = arr[2]
arr[2] = temp
Always use .copy() when storing a row in a temporary variable for swapping. Without it, NumPy creates a view (a reference to the same data), not a separate copy, causing the swap to produce incorrect results.
Method 4: Using np.roll() for Circular Row Shifts
np.roll() shifts all rows by a specified number of positions, wrapping rows from the bottom to the top (or vice versa). This is not a swap of two specific rows but rather a circular rotation:
import numpy as np
arr = np.array([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
[10, 11, 12]
])
print("Original:")
print(arr)
# Roll rows by 2 positions (rows shift down, bottom rows wrap to top)
rolled = np.roll(arr, shift=2, axis=0)
print("\nAfter rolling by 2:")
print(rolled)
Output:
Original:
[[ 1 2 3]
[ 4 5 6]
[ 7 8 9]
[10 11 12]]
After rolling by 2:
[[ 7 8 9]
[10 11 12]
[ 1 2 3]
[ 4 5 6]]
The last two rows wrap around to the top. This is useful for cyclic data but is not a targeted swap of two specific rows.
Creating a Reusable Swap Function
For repeated use, wrap the swap logic in a function:
import numpy as np
def swap_rows(arr, row1, row2):
"""Swap two rows in a NumPy array in place."""
arr[[row1, row2]] = arr[[row2, row1]]
# Example usage
arr = np.array([
[1, 1, 1],
[2, 2, 2],
[3, 3, 3],
[4, 4, 4]
])
print("Before:")
print(arr)
swap_rows(arr, 0, 3)
print("\nAfter swapping rows 0 and 3:")
print(arr)
Output:
Before:
[[1 1 1]
[2 2 2]
[3 3 3]
[4 4 4]]
After swapping rows 0 and 3:
[[4 4 4]
[2 2 2]
[3 3 3]
[1 1 1]]
Swapping Columns Instead of Rows
The same techniques work for columns - just apply the indexing to the column axis:
import numpy as np
arr = np.array([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
])
# Swap column 0 and column 2
arr[:, [0, 2]] = arr[:, [2, 0]]
print(arr)
Output:
[[3 2 1]
[6 5 4]
[9 8 7]]
Method Comparison
| Method | Modifies Original | Swaps Specific Rows | Best For |
|---|---|---|---|
arr[[i, j]] = arr[[j, i]] | Yes | Yes | Swapping two specific rows - recommended |
arr[[2, 0, 1]] (fancy indexing) | No (creates copy) | Yes (any reordering) | Rearranging multiple rows at once |
Temp variable with .copy() | Yes | Yes | Explicit, readable swap logic |
np.roll() | No (creates copy) | No (circular shift) | Rotating all rows cyclically |
For most use cases, advanced indexing (arr[[i, j]] = arr[[j, i]]) is the best choice - it's concise, efficient, modifies the array in place, and clearly communicates the intent of swapping two rows.