Skip to main content

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]]

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.

tip

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.

info

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
danger

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

MethodModifies OriginalSwaps Specific RowsBest For
arr[[i, j]] = arr[[j, i]]YesYesSwapping 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()YesYesExplicit, 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.