深入理解 NumPy 數(shù)組的交換(Swapping)的實(shí)現(xiàn)
一、數(shù)組交換的核心定義
數(shù)組交換本質(zhì)是調(diào)整數(shù)組中元素或維度的位置,主要分為兩類場景:
- 元素級交換:交換數(shù)組中指定位置的單個 / 多個元素(如交換索引 0 和索引 5 的元素);
- 維度級交換:交換數(shù)組的行 / 列、或調(diào)整維度的整體順序(如交換二維數(shù)組的第 1 列和第 3 列、交換三維數(shù)組的維度 0 和維度 2)。
NumPy 實(shí)現(xiàn)交換的核心優(yōu)勢是向量化操作,無需循環(huán),直接通過索引 / 切片即可高效完成。
二、基礎(chǔ)交換:單個 / 多個元素交換
這是最直觀的交換場景,核心邏輯是「通過索引直接賦值」,利用 NumPy 支持的多元素同時(shí)賦值特性(無需臨時(shí)變量)。
示例 1:一維數(shù)組交換單個元素
import numpy as np
# 一維數(shù)組(模擬10個學(xué)生分?jǐn)?shù))
scores = np.array([85, 92, 78, 90, 88, 76, 95, 81, 89, 93])
print("原始數(shù)組:", scores)
# 交換索引1(92)和索引5(76)的元素(無需臨時(shí)變量)
scores[1], scores[5] = scores[5], scores[1]
print("交換后數(shù)組:", scores) # [85 76 78 90 88 92 95 81 89 93]示例 2:一維數(shù)組交換多個連續(xù)元素(切片)
import numpy as np
arr = np.array([1,2,3,4,5,6,7,8])
print("原始數(shù)組:", arr)
# 交換前3個元素(0:3)和后3個元素(5:8)
arr[0:3], arr[5:8] = arr[5:8].copy(), arr[0:3].copy()
# 注意:必須加.copy(),否則切片是視圖,賦值會相互覆蓋
print("交換后數(shù)組:", arr) # [6 7 8 4 5 1 2 3]關(guān)鍵說明:切片交換時(shí),若直接用 arr[0:3], arr[5:8] = arr[5:8], arr[0:3],由于切片是視圖,第一步賦值會修改原數(shù)組,導(dǎo)致第二步賦值拿到的是已修改的數(shù)據(jù),最終結(jié)果錯誤。必須用 .copy() 生成獨(dú)立拷貝。
示例 3:二維數(shù)組交換單個元素
import numpy as np
# 二維數(shù)組(3天×4小時(shí)溫度)
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("原始數(shù)組:\n", temp)
# 交換(0,1)(第1天第2小時(shí))和(2,3)(第3天第4小時(shí))的元素
temp[0,1], temp[2,3] = temp[2,3], temp[0,1]
print("交換后數(shù)組:\n", temp)輸出:
原始數(shù)組:
[[5.2 6.1 7.3 8.2]
[4.8 5.5 6.7 7.9]
[6.3 7.2 8.1 9.0]]
交換后數(shù)組:
[[5.2 9.0 7.3 8.2]
[4.8 5.5 6.7 7.9]
[6.3 7.2 8.1 6.1]]
三、核心交換:二維數(shù)組的行 / 列交換
這是日常使用中最高頻的交換場景,核心是「通過行 / 列索引切片實(shí)現(xiàn)整行 / 整列交換」。
1. 交換兩行(整行)
語法:arr[行索引1], arr[行索引2] = arr[行索引2], arr[行索引1]
import numpy as np
# 二維數(shù)組(4行3列)
arr = np.array([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
[10, 11, 12]
])
print("原始數(shù)組:\n", arr)
# 交換第1行(索引0)和第3行(索引2)
arr[0], arr[2] = arr[2].copy(), arr[0].copy()
# 加.copy()更穩(wěn)妥,避免視圖覆蓋(低版本NumPy可能有問題)
print("交換第1/3行后:\n", arr)輸出:
原始數(shù)組:
[[ 1 2 3]
[ 4 5 6]
[ 7 8 9]
[10 11 12]]
交換第1/3行后:
[[ 7 8 9]
[ 4 5 6]
[ 1 2 3]
[10 11 12]]
2. 交換兩列(整列)
語法:arr[:, 列索引1], arr[:, 列索引2] = arr[:, 列索引2], arr[:, 列索引1]
import numpy as np
arr = np.array([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
[10, 11, 12]
])
print("原始數(shù)組:\n", arr)
# 交換第2列(索引1)和第3列(索引2)
arr[:, 1], arr[:, 2] = arr[:, 2].copy(), arr[:, 1].copy()
print("交換第2/3列后:\n", arr)輸出:
原始數(shù)組:
[[ 1 2 3]
[ 4 5 6]
[ 7 8 9]
[10 11 12]]
交換第2/3列后:
[[ 1 3 2]
[ 4 6 5]
[ 7 9 8]
[10 12 11]]
3. 交換多行 / 多列(批量)
import numpy as np
arr = np.arange(16).reshape(4,4)
print("原始數(shù)組:\n", arr)
# 交換前兩行(0:2)和后兩行(2:4)
arr[0:2], arr[2:4] = arr[2:4].copy(), arr[0:2].copy()
print("交換前兩行/后兩行:\n", arr)
# 重置數(shù)組
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)四、進(jìn)階交換:維度(軸)交換
高維數(shù)組(三維 / 四維)的交換核心是「調(diào)整維度的整體順序」,主要通過 np.swapaxes() 和 arr.transpose() 實(shí)現(xiàn)(swapaxes 更專注于 “交換兩個維度”)。
1. 核心函數(shù):np.swapaxes ()
語法:np.swapaxes(arr, axis1, axis2) 或 arr.swapaxes(axis1, axis2)
axis1/axis2:要交換的兩個維度編號;- 返回值:維度交換后的新數(shù)組(視圖,共享內(nèi)存)。
示例 1:二維數(shù)組交換維度(等價(jià)于轉(zhuǎn)置)
二維數(shù)組的維度 0 = 行、維度 1 = 列,交換維度 0 和 1 等價(jià)于轉(zhuǎn)置:
import numpy as np
arr = np.array([[1,2,3],[4,5,6]])
print("原始數(shù)組:\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)(等價(jià)于arr.T)示例 2:三維數(shù)組交換維度
import numpy as np
# 三維數(shù)組:形狀(2,3,4) → 維度0=2,維度1=3,維度2=4
arr_3d = np.arange(24).reshape(2,3,4)
print("原始三維數(shù)組形狀:", 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)2. 用 transpose 實(shí)現(xiàn)多維度交換
transpose 可同時(shí)調(diào)整多個維度的順序,比 swapaxes 更靈活(swapaxes 僅能交換兩個維度):
import numpy as np
arr_3d = np.arange(24).reshape(2,3,4)
print("原始形狀:", arr_3d.shape) # (2,3,4)
# 交換維度順序?yàn)?(2,0,1) → 等價(jià)于先交換0和2,再交換1和2
arr_trans = arr_3d.transpose(2,0,1)
print("transpose調(diào)整后形狀:", arr_trans.shape) # (4,2,3)五、實(shí)戰(zhàn)場景:交換的典型應(yīng)用
場景 1:調(diào)整圖像數(shù)據(jù)維度順序
圖像數(shù)據(jù)常見維度順序:(高度, 寬度, 通道)(HWC) ↔ (通道, 高度, 寬度)(CHW),可通過維度交換實(shí)現(xiàn):
import numpy as np
# 模擬圖像數(shù)據(jù):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:打亂數(shù)據(jù)集的行順序(隨機(jī)交換)
import numpy as np
# 模擬數(shù)據(jù)集:100個樣本 × 5個特征
data = np.random.rand(100,5)
# 生成隨機(jī)索引(打亂行順序)
random_idx = np.random.permutation(100)
# 通過索引交換實(shí)現(xiàn)行打亂(等價(jià)于隨機(jī)重排)
data_shuffled = data[random_idx]
print("原始數(shù)據(jù)前3行:\n", data[:3])
print("打亂后數(shù)據(jù)前3行:\n", data_shuffled[:3])場景 3:修正溫度數(shù)據(jù)的列順序
import numpy as np
# 模擬溫度數(shù)據(jù):31天 × 4列(凌晨、上午、下午、晚上),但列順序錯誤(凌晨和晚上顛倒)
temp = np.random.normal(5,6,(31,4)).round(1)
print("原始列順序:凌晨、上午、下午、晚上 → 實(shí)際是:晚上、上午、下午、凌晨")
# 交換第0列(晚上)和第3列(凌晨)
temp[:, 0], temp[:, 3] = temp[:, 3].copy(), temp[:, 0].copy()
print("修正后溫度數(shù)據(jù)前3行:\n", temp[:3])六、避坑點(diǎn)與最佳實(shí)踐
1. 核心避坑點(diǎn)
- ? 切片交換未加
.copy():直接用arr[0:2], arr[2:4] = arr[2:4], arr[0:2]會導(dǎo)致數(shù)據(jù)覆蓋,必須加.copy(); - ? 混淆維度編號:高維數(shù)組交換維度時(shí),記錯維度 0/1/2 的含義(如把圖像的通道維度編號記錯);
- ? 認(rèn)為
swapaxes返回新數(shù)組:實(shí)際是視圖(共享內(nèi)存),修改會影響原數(shù)組,需獨(dú)立則加.copy(); - ? 交換多行 / 列時(shí)索引錯誤:如
arr[0,2]是單個元素,而非第 0 和第 2 行(正確寫法是arr[[0,2]])。
2. 最佳實(shí)踐
- ? 單個元素交換:直接
arr[i], arr[j] = arr[j], arr[i](無需 copy); - ? 切片 / 整行 / 整列交換:必須加
.copy(),避免視圖覆蓋; - ? 維度交換:二維數(shù)組用
arr.T或swapaxes(0,1),高維數(shù)組用swapaxes(交換兩個維度)或transpose(調(diào)整多維度); - ? 隨機(jī)交換行:用
np.random.permutation生成隨機(jī)索引,通過索引重排(高效且避免手動交換); - ? 驗(yàn)證交換結(jié)果:通過
shape檢查維度,通過索引取值驗(yàn)證元素位置是否正確。
總結(jié)
- NumPy 數(shù)組交換分為「元素級」和「維度級」兩類:
- 元素級:通過索引 / 切片賦值實(shí)現(xiàn),切片交換需加
.copy(); - 維度級:整行 / 列交換用索引切片,高維維度交換用
swapaxes/transpose;
- 元素級:通過索引 / 切片賦值實(shí)現(xiàn),切片交換需加
- 核心語法:
- 單個元素:
arr[i], arr[j] = arr[j], arr[i]; - 整行交換:
arr[row1], arr[row2] = arr[row2].copy(), arr[row1].copy(); - 整列交換:
arr[:, col1], arr[:, col2] = arr[:, col2].copy(), arr[:, col1].copy(); - 維度交換:
arr.swapaxes(axis1, axis2);
- 單個元素:
- 避坑關(guān)鍵:切片交換必須加
.copy(),維度交換牢記維度編號,驗(yàn)證交換結(jié)果; - 常用場景:調(diào)整數(shù)據(jù)列順序、圖像維度轉(zhuǎn)換、打亂數(shù)據(jù)集、修正數(shù)據(jù)行 / 列位置。
到此這篇關(guān)于深入理解 NumPy 數(shù)組的交換(Swapping)的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)NumPy 數(shù)組交換內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python numpy生成等差數(shù)列、等比數(shù)列的實(shí)例
今天小編就為大家分享一篇python numpy生成等差數(shù)列、等比數(shù)列的實(shí)例,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-02-02
Django實(shí)現(xiàn)將views.py中的數(shù)據(jù)傳遞到前端html頁面,并展示
這篇文章主要介紹了Django實(shí)現(xiàn)將views.py中的數(shù)據(jù)傳遞到前端html頁面并展示,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-03-03
python異步的ASGI與Fast Api實(shí)現(xiàn)
本文主要介紹了python異步的ASGI與Fast Api實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-07-07
python GUI庫圖形界面開發(fā)之PyQt5動態(tài)加載QSS樣式文件
這篇文章主要介紹了python GUI庫圖形界面開發(fā)之PyQt5動態(tài)加載QSS樣式表,需要的朋友可以參考下2020-02-02
利用 Python 實(shí)現(xiàn)隨機(jī)相對強(qiáng)弱指數(shù) StochRSI
隨機(jī)相對強(qiáng)弱指數(shù)簡稱為StochRSI,是一種技術(shù)分析指標(biāo),用于確定資產(chǎn)是否處于超買或超賣狀態(tài),也用于確定當(dāng)前市場的態(tài)勢。本篇文章小編九來為大家介紹隨機(jī)相對強(qiáng)弱指數(shù)簡稱為StochRSI,需要的朋友可以參考下面文章的具體內(nèi)容2021-09-09
Python?數(shù)據(jù)篩選功能實(shí)現(xiàn)
這篇文章主要介紹了Python?數(shù)據(jù)篩選,無論是在數(shù)據(jù)分析還是數(shù)據(jù)挖掘的時(shí)候,數(shù)據(jù)篩選總會涉及到,這里我總結(jié)了一下python中列表,字典,數(shù)據(jù)框中一些常用的數(shù)據(jù)篩選的方法,需要的朋友可以參考下2023-04-04

