深入理解 NumPy 数组的交换(Swapping)的实现

陆遥
陆遥
发布时间:2026-10-11 | 3人浏览过
原创

本文深入解析 NumPy 数组交换的多种实现方式,涵盖元素级、行列级及维度级的交换操作。重点讲解切片赋值时 .copy() 的必要性,以及 swapaxes 和 transpose 在高维数组中的应用,并提供图像数据转换与数据集打乱的实战案例。

一、数组交换的核心定义

在 NumPy 中,数组交换主要分为两类:元素级交换和维度级交换。元素级交换针对指定位置的单个或多个元素,而维度级交换则涉及行、列或整体维度的顺序调整。NumPy 通过向量化操作实现高效交换,无需编写循环,直接利用索引或切片即可完成。

二、基础交换:单个与多个元素

基础交换的核心逻辑是通过索引直接赋值。利用 NumPy 的多元素同时赋值特性,无需临时变量即可完成交换。然而,切片交换直接使用会导致数据错误,因为第一步赋值修改原数组会影响第二步。因此,必须使用 .copy() 生成独立拷贝。

1. 一维数组元素交换

import numpy as np
# 一维数组(模拟10个学生分数)
scores = np.array([85, 92, 78, 90, 88, 76, 95, 81, 89, 93])
print("原始数组:", scores)
# 交换索引1(92)和索引5(76)的元素(无需临时变量)
scores[1], scores[5] = scores[5], scores[1]
print("交换后数组:", scores)  # [85 76 78 90 88 92 95 81 89 93]

2. 一维数组切片交换

import numpy as np
arr = np.array([1,2,3,4,5,6,7,8])
print("原始数组:", arr)
# 交换前3个元素(0:3)和后3个元素(5:8)
arr[0:3], arr[5:8] = arr[5:8].copy(), arr[0:3].copy()
# 注意:必须加.copy(),否则切片是视图,赋值会相互覆盖
print("交换后数组:", arr)  # [6 7 8 4 5 1 2 3]

3. 二维数组元素交换

import numpy as np
# 二维数组(3天×4小时温度)
temp = np.array([
    [5.2, 6.1, 7.3, 8.2],
    [4.8, 5.5, 6.7, 7.9],
    [6.3, 7.2, 8.1, 9.0]
])
print("原始数组:\n", temp)
# 交换(0,1)(第1天第2小时)和(2,3)(第3天第4小时)的元素
temp[0,1], temp[2,3] = temp[2,3], temp[0,1]
print("交换后数组:\n", temp)

三、核心交换:二维数组的行/列交换

二维数组交换通过行/列索引切片实现。交换两行的语法为 arr[i], arr[j] = arr[j], arr[i],交换两列的语法为 arr[:, i], arr[:, j] = arr[:, j], arr[:, i]。整行交换直接通过索引切片完成,整列交换通过冒号选取所有行。

1. 行交换

import numpy as np
# 二维数组(4行3列)
arr = np.array([
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9],
    [10, 11, 12]
])
print("原始数组:\n", arr)
# 交换第1行(索引0)和第3行(索引2)
arr[0], arr[2] = arr[2].copy(), arr[0].copy()
# 加.copy()更稳妥,避免视图覆盖(低版本NumPy可能有问题)
print("交换第1/3行后:\n", arr)

2. 列交换

import numpy as np
arr = np.array([
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9],
    [10, 11, 12]
])
print("原始数组:\n", arr)
# 交换第2列(索引1)和第3列(索引2)
arr[:, 1], arr[:, 2] = arr[:, 2].copy(), arr[:, 1].copy()
print("交换第2/3列后:\n", arr)

3. 多行/列交换

import numpy as np
arr = np.arange(16).reshape(4,4)
print("原始数组:\n", arr)
# 交换前两行(0:2)和后两行(2:4)
arr[0:2], arr[2:4] = arr[2:4].copy(), arr[0:2].copy()
print("交换前两行/后两行:\n", arr)
# 重置数组
arr = np.arange(16).reshape(4,4)
# 交换前两列(:,0:2)和后两列(:,2:4)
arr[:, 0:2], arr[:, 2:4] = arr[:, 2:4].copy(), arr[:, 0:2].copy()
print("交换前两列/后两列:\n", arr)

四、进阶交换:维度(轴)交换

高维数组交换的核心是调整维度整体顺序,主要通过 np.swapaxes() 和 arr.transpose() 实现。swapaxes 专注于交换两个维度,语法为 np.swapaxes(arr, axis1, axis2),其中 axis1 和 axis2 为要交换的维度编号。返回值为视图,共享原数组内存。二维数组交换维度 0 和 1 等价于转置。transpose 可同时调整多个维度顺序,而 swapaxes 仅能交换两个维度。

1. 二维数组维度交换

import numpy as np
arr = np.array([[1,2,3],[4,5,6]])
print("原始数组:\n", arr)
print("原始形状:", arr.shape)  # (2,3)
# 交换维度0和1
arr_swap = arr.swapaxes(0, 1)
print("交换维度后:\n", arr_swap)
print("交换后形状:", arr_swap.shape)  # (3,2)(等价于arr.T)

2. 三维数组维度交换

import numpy as np
# 三维数组:形状(2,3,4) → 维度0=2,维度1=3,维度2=4
arr_3d = np.arange(24).reshape(2,3,4)
print("原始三维数组形状:", arr_3d.shape)  # (2,3,4)
# 交换维度0和维度2
arr_swap = arr_3d.swapaxes(0, 2)
print("交换维度0/2后形状:", arr_swap.shape)  # (4,3,2)
# 交换维度1和维度2
arr_swap2 = arr_3d.swapaxes(1, 2)
print("交换维度1/2后形状:", arr_swap2.shape)  # (2,4,3)

3. 使用 transpose 调整维度顺序

import numpy as np
arr_3d = np.arange(24).reshape(2,3,4)
print("原始形状:", arr_3d.shape)  # (2,3,4)
# 交换维度顺序为 (2,0,1) → 等价于先交换0和2,再交换1和2
arr_trans = arr_3d.transpose(2,0,1)
print("transpose调整后形状:", arr_trans.shape)  # (4,2,3)

五、实战场景:交换的典型应用

图像数据常见维度顺序为 HWC 或 CHW,可通过维度交换实现 HWC 与 CHW 转换。其他场景包括打乱数据集的行顺序和修正温度数据的列顺序。

1. 图像数据维度转换

import numpy as np
# 模拟图像数据:2张图片 × 32高度 × 32宽度 × 3通道(HWC)
img_hwc = np.random.randint(0,255, (2,32,32,3))
print("HWC格式形状:", img_hwc.shape)  # (2,32,32,3)
# 交换维度1(高度)和维度3(通道)?→ 更简单的方式:transpose
img_chw = img_hwc.transpose(0,3,1,2)
print("CHW格式形状:", img_chw.shape)  # (2,3,32,32)
# 再交换回来(CHW → HWC)
img_hwc2 = img_chw.transpose(0,2,3,1)
print("还原后形状:", img_hwc2.shape)  # (2,32,32,3)

2. 数据集行打乱

import numpy as np
# 模拟数据集:100个样本 × 5个特征
data = np.random.rand(100,5)
# 生成随机索引(打乱行顺序)
random_idx = np.random.permutation(100)
# 通过索引交换实现行打乱(等价于随机重排)
data_shuffled = data[random_idx]
print("原始数据前3行:\n", data[:3])
print("打乱后数据前3行:\n", data_shuffled[:3])

3. 修正温度数据列顺序

import numpy as np
# 模拟温度数据:31天 × 4列(凌晨、上午、下午、晚上),但列顺序错误(凌晨和晚上颠倒)
temp = np.random.normal(5,6,(31,4)).round(1)
print("原始列顺序:凌晨、上午、下午、晚上 → 实际是:晚上、上午、下午、凌晨")
# 交换第0列(晚上)和第3列(凌晨)
temp[:, 0], temp[:, 3] = temp[:, 3].copy(), temp[:, 0].copy()
print("修正后温度数据前3行:\n", temp[:3])

六、避坑点与最佳实践

  • 切片交换未加 .copy() 会导致数据覆盖。
  • 高维数组交换时易混淆维度编号。
  • swapaxes 返回视图,修改影响原数组。
  • 交换多行/列时索引写法易出错。
  • arr[[0,2]] 表示第 0 和第 2 行,而 arr[0,2] 表示单个元素。
  • 单个元素交换无需使用 .copy(),但切片或整行/列交换必须加 .copy()。
  • 二维数组可用 arr.T 或 swapaxes(0,1)。
  • 高维数组用 swapaxes 或 transpose。
  • 随机交换行可用 np.random.permutation,通过索引重排避免手动交换。
  • 交换后需通过 shape 检查维度,并通过索引取值验证元素位置。

总结

NumPy 数组交换分为元素级和维度级。元素级通过索引或切片赋值实现,切片交换必须加 .copy()。整行/列交换用索引切片,高维维度交换用 swapaxes 或 transpose。常用场景包括调整列顺序、图像维度转换、打乱数据集和修正数据行/列位置。

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表