
- NumPy 教程
- NumPy - 首頁
- NumPy - 簡介
- NumPy - 環境
- NumPy 陣列
- NumPy - Ndarray 物件
- NumPy - 資料型別
- NumPy 建立和運算元組
- NumPy - 陣列建立例程
- NumPy - 陣列操作
- NumPy - 從現有資料建立陣列
- NumPy - 從數值範圍建立陣列
- NumPy - 迭代陣列
- NumPy - 重塑陣列
- NumPy - 連線陣列
- NumPy - 堆疊陣列
- NumPy - 分割陣列
- NumPy - 展平陣列
- NumPy - 轉置陣列
- NumPy 索引和切片
- NumPy - 索引和切片
- NumPy - 高階索引
- NumPy 陣列屬性和操作
- NumPy - 陣列屬性
- NumPy - 陣列形狀
- NumPy - 陣列大小
- NumPy - 陣列步幅
- NumPy - 陣列元素大小
- NumPy - 廣播
- NumPy - 算術運算
- NumPy - 陣列加法
- NumPy - 陣列減法
- NumPy - 陣列乘法
- NumPy - 陣列除法
- NumPy 高階陣列操作
- NumPy - 交換陣列的軸
- NumPy - 位元組交換
- NumPy - 複製與檢視
- NumPy - 元素級陣列比較
- NumPy - 過濾陣列
- NumPy - 連線陣列
- NumPy - 排序、搜尋和計數函式
- NumPy - 搜尋陣列
- NumPy - 陣列的並集
- NumPy - 查詢唯一行
- NumPy - 建立日期時間陣列
- NumPy - 二元運算子
- NumPy - 字串函式
- NumPy - 數學函式
- NumPy - 統計函式
- NumPy - 矩陣庫
- NumPy - 線性代數
- NumPy - Matplotlib
- NumPy - 使用 Matplotlib 繪製直方圖
- NumPy - NumPy 的 I/O
- NumPy 排序和高階操作
- NumPy - 排序陣列
- NumPy - 沿軸排序
- NumPy - 使用花式索引排序
- NumPy - 結構化陣列
- NumPy - 建立結構化陣列
- NumPy - 操作結構化陣列
- NumPy - 欄位訪問
- NumPy - 記錄陣列
- Numpy - 載入陣列
- Numpy - 儲存陣列
- NumPy - 將值追加到陣列
- NumPy - 交換陣列的列
- NumPy - 向陣列插入軸
- NumPy 處理缺失資料
- NumPy - 處理缺失資料
- NumPy - 識別缺失值
- NumPy - 刪除缺失資料
- NumPy - 估算缺失資料
- NumPy 效能最佳化
- NumPy - 使用陣列進行效能最佳化
- NumPy - 使用陣列進行向量化
- NumPy - 陣列的記憶體佈局
- Numpy 線性代數
- NumPy - 線性代數
- NumPy - 矩陣庫
- NumPy - 矩陣加法
- NumPy - 矩陣減法
- NumPy - 矩陣乘法
- NumPy - 元素級矩陣運算
- NumPy - 點積
- NumPy - 矩陣求逆
- NumPy - 行列式計算
- NumPy - 特徵值
- NumPy - 特徵向量
- NumPy - 奇異值分解
- NumPy - 求解線性方程組
- NumPy - 矩陣範數
- NumPy 元素級矩陣運算
- NumPy - 求和
- NumPy - 求平均值
- NumPy - 求中位數
- NumPy - 求最小值
- NumPy - 求最大值
- NumPy 集合運算
- NumPy - 唯一元素
- NumPy - 交集
- NumPy - 並集
- NumPy - 差集
- NumPy 有用資源
- NumPy 編譯器
- NumPy - 快速指南
- NumPy - 有用資源
- NumPy - 討論
NumPy - 複製與檢視
在 NumPy 中,當您對陣列執行操作時,結果可能是原始資料的副本或只是原始資料的檢視。瞭解這兩者之間的區別對於有效的記憶體管理以及避免程式碼中的意外副作用非常重要。
在 NumPy 中建立副本
我們可以使用 copy() 函式在 NumPy 中顯式地建立陣列的副本。此函式生成一個新陣列,並將原始陣列中的資料複製到此新陣列中。
當您在 NumPy 中建立陣列的副本時,資料將被完全複製。這意味著對副本進行的更改不會影響原始陣列,反之亦然。當您需要使用修改後的陣列版本而不更改原始資料時,副本很有用。
示例
在以下示例中,修改copied_array不會影響original_array,這證明了這兩個陣列的獨立性:
import numpy as np # Original array original_array = np.array([1, 2, 3]) # Creating a copy copied_array = original_array.copy() # Modifying the copy copied_array[0] = 10 print("Original Array:", original_array) print("Copied Array:", copied_array)
獲得以下輸出:
Original Array: [1 2 3] Copied Array: [10 2 3]
淺複製與深複製
在 NumPy 陣列的上下文中,淺複製和深複製之間的區別對於理解複製資料的方式很重要。
淺複製
陣列的淺複製建立一個新的陣列物件,但如果這些元素本身是陣列或其他複雜物件,則它不會建立原始陣列中包含的元素的副本。
相反,新陣列仍然引用與原始陣列相同的元素。這意味著對元素內容的更改將影響原始陣列和複製陣列。
- 陣列級副本 - 在 NumPy 陣列的情況下,淺複製意味著雖然複製了頂層陣列物件,但底層資料緩衝區沒有被複制。新陣列只是同一資料的新的檢視。
- 用法 - 當您需要一個新的陣列物件但又想避免複製大量資料的開銷時,淺複製很有用。
示例
在此示例中,修改shallow_copy也會修改original_array,因為它們共享相同的基礎資料:
import numpy as np # Original array original_array = np.array([[1, 2, 3], [4, 5, 6]]) # Shallow copy shallow_copy = original_array.view() # Modify an element in the shallow copy shallow_copy[0, 0] = 100 print("Original Array:") print(original_array) print("\nShallow Copy:") print(shallow_copy)
這將產生以下結果:
Original Array: [[100 2 3] [ 4 5 6]] Shallow Copy: [[100 2 3] [ 4 5 6]]
深複製
另一方面,深複製會建立一個新的陣列物件以及它包含的所有資料的副本。這意味著對新陣列進行的任何更改都不會影響原始陣列,反之亦然。新陣列中的資料與原始陣列中的資料完全獨立。
- 完全複製 - 在 NumPy 的上下文中,深複製涉及複製陣列的整個資料緩衝區,以確保新陣列與原始陣列完全分離。
- 用法 - 當您需要獨立於原始陣列使用資料時,深複製非常重要,尤其是在資料可能以不應影響原始資料的方式修改時。
示例
在這種情況下,修改deep_copy不會影響original_array,這證明了這兩個陣列的獨立性:
import numpy as np # Original array original_array = np.array([[1, 2, 3], [4, 5, 6]]) # Deep copy deep_copy = original_array.copy() # Modify an element in the deep copy deep_copy[0, 0] = 100 print("Original Array:") print(original_array) print("\nDeep Copy:") print(deep_copy)
以下是上述程式碼的輸出:
Original Array: [[1 2 3] [4 5 6]] Deep Copy: [[100 2 3] [ 4 5 6]]
複製子陣列
為了避免在處理子陣列時修改原始陣列,您應該建立子陣列的副本。當您需要獨立於原始資料操作或分析子陣列時,這很有用。
子陣列只是現有 NumPy 陣列的一部分。您可以使用切片技術提取子陣列。
例如,如果您有一個二維陣列,您可以透過沿著其行和列進行切片來提取一個較小的二維子陣列。但是,預設情況下,切片會建立原始陣列的檢視,而不是單獨的副本。這意味著對子陣列的更改也將影響原始陣列,除非您顯式地建立副本。
示例
在下面的示例中,sub_array由於使用了 copy() 函式,因此是一個完全獨立的陣列:
import numpy as np # Original 2D array original_array = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) # Creating a copy of the subarray sub_array = original_array[0:2].copy() sub_array[0] = 20 print("Original Array after subarray copy:", original_array) print("Subarray:", sub_array)
獲得的輸出如下所示:
Original Array after subarray copy: [[1 2 3] [4 5 6] [7 8 9]] Subarray: [[20 20 20] [ 4 5 6]]
在 NumPy 中建立檢視
當您切片陣列或執行某些操作(如重塑)時會建立檢視。資料不會被複制;相反,新陣列只是檢視原始資料的一種不同方式。
換句話說,檢視是一個新的陣列物件,它檢視與原始陣列相同的資料。這意味著,如果您修改檢視,更改將反映在原始陣列中,反之亦然。
示例
在此示例中,修改view_array直接影響original_array,表明它們共享相同的資料:
import numpy as np # Original array original_array = np.array([1, 2, 3]) view_array = original_array[0:2] # Modifying the view view_array[0] = 30 print("Original Array after view modification:", original_array) print("View Array:", view_array)
執行上述程式碼後,我們將獲得以下輸出:
Original Array after view modification: [30 2 3] View Array: [30 2]
何時返回檢視?
並非所有切片或操作都會導致檢視。如果陣列的記憶體佈局發生變化,NumPy 可能會返回副本而不是檢視。
來自切片的檢視
NumPy 中返回檢視的最常見情況是當您切片陣列時。切片是透過指定一系列索引來提取陣列一部分的方法。NumPy 返回一個檢視,而不是建立一個具有自身資料的新陣列,這意味著切片陣列與原始陣列共享相同的資料。
示例
在此示例中,view_array是original_array的檢視。資料不會被複制,並且兩個陣列共享相同的底層記憶體。這意味著對“view_array”進行的任何更改也將影響“original_array”:
import numpy as np # Original array original_array = np.array([1, 2, 3, 4, 5]) # Creating a view by slicing the original array view_array = original_array[1:4] print("Original Array:") print(original_array) print("\nView Array (Sliced):") print(view_array)
產生的結果如下:
Original Array: [1 2 3 4 5] View Array (Sliced): [2 3 4]
來自重塑的檢視
返回檢視的另一種常見情況是當您重塑陣列時。重塑會更改陣列的形狀(即每個維度中的元素數),而不更改底層資料。在可能的情況下,NumPy 會以新形狀返回原始陣列的檢視。
示例
這裡,reshaped_array是original_array的檢視,只是以“2x3”格式呈現。資料保持不變,修改“reshaped_array”也會修改“original_array”:
import numpy as np # Original 1D array original_array = np.array([1, 2, 3, 4, 5, 6]) # Reshaping the array into a 2x3 matrix reshaped_array = original_array.reshape(2, 3) print("Original Array:") print(original_array) print("\nReshaped Array (View):") print(reshaped_array)
我們獲得以下輸出:
Original Array:[1 2 3 4 5 6] Reshaped Array (View): [[1 2 3] [4 5 6]]
來自轉置的檢視
轉置陣列涉及將其翻轉過其對角線,將行轉換為列,反之亦然。當您使用np.transpose()函式或.T屬性轉置陣列時,NumPy 會在可能的情況下返回檢視,而不是副本。
示例
在這種情況下,transposed_array是original_array的檢視,但軸已交換。底層資料保持不變,對“transposed_array”的更改將反映在“original_array”中:
import numpy as np # Original 2D array original_array = np.array([[1, 2, 3], [4, 5, 6]]) # Transposing the array transposed_array = original_array.T print("Original Array:") print(original_array) print("\nTransposed Array (View):") print(transposed_array)
獲得以下輸出:
Original Array: [[1 2 3] [4 5 6]] Transposed Array (View): [[1 4] [2 5] [3 6]]
base 屬性
在 NumPy 中,陣列的base屬性檢查陣列是另一個數組的檢視還是副本。它是對從中派生當前陣列的原始陣列的引用。
如果當前陣列是另一個數組的檢視,“base”將指向該原始陣列。如果當前陣列不是檢視(即它是原始陣列或深複製),則“base”將為None。
示例:原始陣列的 base 屬性
當您建立陣列時,其 base 屬性將為 None,因為它就是原始陣列:
import numpy as np # Creating an original array original_array = np.array([10, 20, 30, 40, 50]) # Checking the base attribute print("Base of original array:", original_array.base)
這將產生以下結果:
Base of original array: None
示例:檢視的 base 屬性
當您建立陣列的檢視(例如,透過切片)時,檢視的 base 屬性將指向原始陣列:
import numpy as np # Creating an original array original_array = np.array([10, 20, 30, 40, 50]) # Creating a view of the original array view_array = original_array[1:4] # Checking the base attribute print("Base of view array:", view_array.base)
以下是上述程式碼的輸出:
Base of view array: [10 20 30 40 50]
示例:副本的 base 屬性
如果您建立陣列的副本,則 base 屬性將為 None,表示複製的陣列獨立於原始陣列:
import numpy as np # Creating an original array original_array = np.array([10, 20, 30, 40, 50]) # Creating a copy of the original array copy_array = original_array.copy() # Checking the base attribute print("Base of copy array:", copy_array.base)
以下是上述程式碼的輸出:
Base of copy array: None