陣列建立#
另請參閱
簡介#
有 6 種建立陣列的通用機制
從其他 Python 結構轉換(即列表和元組)
NumPy 內建陣列建立函數(例如 arange、ones、zeros 等)
複製、連接或變更現有陣列
從磁碟讀取陣列,無論是標準或自訂格式
透過使用字串或緩衝區,從原始位元組建立陣列
使用特殊函式庫函數(例如 random)
您可以使用這些方法來建立 ndarrays 或 結構化陣列。本文檔將涵蓋 ndarray 建立的通用方法。
1) 將 Python 序列轉換為 NumPy 陣列#
NumPy 陣列可以使用 Python 序列(如列表和元組)來定義。列表和元組分別使用 [...]
和 (...)
定義。列表和元組可以定義 ndarray 建立
數字列表將建立一維陣列,
列表的列表將建立二維陣列,
更深層巢狀的列表將建立更高維度的陣列。一般來說,任何陣列物件在 NumPy 中都稱為 ndarray。
>>> import numpy as np
>>> a1D = np.array([1, 2, 3, 4])
>>> a2D = np.array([[1, 2], [3, 4]])
>>> a3D = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
當您使用 numpy.array
定義新陣列時,您應該考慮陣列中元素的 dtype,這可以明確指定。此功能讓您更能控制底層資料結構以及元素在 C/C++ 函數中的處理方式。當值不符合且您正在使用 dtype
時,NumPy 可能會引發錯誤
>>> import numpy as np
>>> np.array([127, 128, 129], dtype=np.int8)
Traceback (most recent call last):
...
OverflowError: Python integer 128 out of bounds for int8
一個 8 位元有號整數表示從 -128 到 127 的整數。將 int8
陣列指定為此範圍之外的整數會導致溢位。此功能經常被誤解。如果您使用不匹配的 dtypes
執行計算,您可能會得到不想要的結果,例如
>>> import numpy as np
>>> a = np.array([2, 3, 4], dtype=np.uint32)
>>> b = np.array([5, 6, 7], dtype=np.uint32)
>>> c_unsigned32 = a - b
>>> print('unsigned c:', c_unsigned32, c_unsigned32.dtype)
unsigned c: [4294967293 4294967293 4294967293] uint32
>>> c_signed32 = a - b.astype(np.int32)
>>> print('signed c:', c_signed32, c_signed32.dtype)
signed c: [-3 -3 -3] int64
請注意,當您使用兩個相同 dtype
的陣列執行運算時:uint32
,結果陣列是相同的類型。當您使用不同的 dtype
執行運算時,NumPy 會指定一個新的類型,以滿足計算中涉及的所有陣列元素,這裡 uint32
和 int32
都可以表示為 int64
。
預設的 NumPy 行為是以 32 或 64 位元有號整數(平台相關且符合 C long
大小)或雙精度浮點數建立陣列。如果您期望您的整數陣列是特定類型,那麼您需要在建立陣列時指定 dtype。
2) NumPy 內建陣列建立函數#
NumPy 有超過 40 個內建函數用於建立陣列,如 陣列建立常式 中所述。這些函數大致可以分為三類,根據它們建立的陣列維度
一維陣列
二維陣列
ndarray
1 - 一維陣列建立函數#
一維陣列建立函數,例如 numpy.linspace
和 numpy.arange
,通常至少需要兩個輸入,start
和 stop
。
numpy.arange
建立具有規律遞增值的陣列。請查看文件以獲取完整資訊和範例。以下顯示一些範例
>>> import numpy as np
>>> np.arange(10)
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> np.arange(2, 10, dtype=float)
array([2., 3., 4., 5., 6., 7., 8., 9.])
>>> np.arange(2, 3, 0.1)
array([2. , 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 2.9])
注意:numpy.arange
的最佳實務是使用整數 start、end 和 step 值。關於 dtype
有一些細微之處。在第二個範例中,定義了 dtype
。在第三個範例中,陣列是 dtype=float
以容納 0.1
的步長。由於捨入誤差,stop
值有時會被包含在內。
numpy.linspace
將建立具有指定元素數量的陣列,並在指定的開始值和結束值之間均勻間隔。例如
>>> import numpy as np
>>> np.linspace(1., 4., 6)
array([1. , 1.6, 2.2, 2.8, 3.4, 4. ])
此建立函數的優點是您可以保證元素的數量以及起點和終點。先前的 arange(start, stop, step)
將不包含值 stop
。
2 - 二維陣列建立函數#
二維陣列建立函數,例如 numpy.eye
、numpy.diag
和 numpy.vander
,定義了表示為二維陣列的特殊矩陣的屬性。
np.eye(n, m)
定義一個二維單位矩陣。其中 i=j(行索引和列索引相等)的元素為 1,其餘為 0,如下所示
>>> import numpy as np
>>> np.eye(3)
array([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])
>>> np.eye(3, 5)
array([[1., 0., 0., 0., 0.],
[0., 1., 0., 0., 0.],
[0., 0., 1., 0., 0.]])
numpy.diag
可以定義一個沿對角線具有給定值的方形二維陣列,或者如果給定一個二維陣列,則返回一個僅包含對角線元素的一維陣列。這兩個陣列建立函數在進行線性代數時可能很有用,如下所示
>>> import numpy as np
>>> np.diag([1, 2, 3])
array([[1, 0, 0],
[0, 2, 0],
[0, 0, 3]])
>>> np.diag([1, 2, 3], 1)
array([[0, 1, 0, 0],
[0, 0, 2, 0],
[0, 0, 0, 3],
[0, 0, 0, 0]])
>>> a = np.array([[1, 2], [3, 4]])
>>> np.diag(a)
array([1, 4])
vander(x, n)
將 Vandermonde 矩陣定義為二維 NumPy 陣列。Vandermonde 矩陣的每一列都是輸入一維陣列或列表或元組 x
的遞減冪,其中最高多項式階數為 n-1
。此陣列建立常式有助於生成線性最小平方模型,如下所示
>>> import numpy as np
>>> np.vander(np.linspace(0, 2, 5), 2)
array([[0. , 1. ],
[0.5, 1. ],
[1. , 1. ],
[1.5, 1. ],
[2. , 1. ]])
>>> np.vander([1, 2, 3, 4], 2)
array([[1, 1],
[2, 1],
[3, 1],
[4, 1]])
>>> np.vander((1, 2, 3, 4), 4)
array([[ 1, 1, 1, 1],
[ 8, 4, 2, 1],
[27, 9, 3, 1],
[64, 16, 4, 1]])
3 - 通用 ndarray 建立函數#
ndarray 建立函數,例如 numpy.ones
、numpy.zeros
和 random
,根據所需的形狀定義陣列。ndarray 建立函數可以透過在元組或列表中指定維度數量和沿該維度的長度來建立任何維度的陣列。
numpy.zeros
將建立一個以 0 值填充的陣列,並具有指定的形狀。預設 dtype 是 float64
>>> import numpy as np
>>> np.zeros((2, 3))
array([[0., 0., 0.],
[0., 0., 0.]])
>>> np.zeros((2, 3, 2))
array([[[0., 0.],
[0., 0.],
[0., 0.]],
[[0., 0.],
[0., 0.],
[0., 0.]]])
numpy.ones
將建立一個以 1 值填充的陣列。它在所有其他方面都與 zeros
相同,如下所示
>>> import numpy as np
>>> np.ones((2, 3))
array([[1., 1., 1.],
[1., 1., 1.]])
>>> np.ones((2, 3, 2))
array([[[1., 1.],
[1., 1.],
[1., 1.]],
[[1., 1.],
[1., 1.],
[1., 1.]]])
random
方法是 default_rng
的結果,它將建立一個以介於 0 和 1 之間的隨機值填充的陣列。它包含在 numpy.random
函式庫中。下面,分別建立了形狀為 (2,3) 和 (2,3,2) 的兩個陣列。種子設定為 42,因此您可以重現這些偽隨機數
>>> import numpy as np
>>> from numpy.random import default_rng
>>> default_rng(42).random((2,3))
array([[0.77395605, 0.43887844, 0.85859792],
[0.69736803, 0.09417735, 0.97562235]])
>>> default_rng(42).random((2,3,2))
array([[[0.77395605, 0.43887844],
[0.85859792, 0.69736803],
[0.09417735, 0.97562235]],
[[0.7611397 , 0.78606431],
[0.12811363, 0.45038594],
[0.37079802, 0.92676499]]])
numpy.indices
將建立一組陣列(堆疊為更高維度的陣列),每個維度一個,每個陣列代表該維度的變化
>>> import numpy as np
>>> np.indices((3,3))
array([[[0, 0, 0],
[1, 1, 1],
[2, 2, 2]],
[[0, 1, 2],
[0, 1, 2],
[0, 1, 2]]])
這對於在規則網格上評估多維函數特別有用。
3) 複製、連接或變更現有陣列#
一旦您建立了陣列,您就可以複製、連接或變更這些現有陣列以建立新陣列。當您將陣列或其元素指定給新變數時,您必須明確地 numpy.copy
陣列,否則該變數將是原始陣列的視圖。請考慮以下範例
>>> import numpy as np
>>> a = np.array([1, 2, 3, 4, 5, 6])
>>> b = a[:2]
>>> b += 1
>>> print('a =', a, '; b =', b)
a = [2 3 3 4 5 6] ; b = [2 3]
在此範例中,您沒有建立新陣列。您建立了一個變數 b
,它查看了 a
的前 2 個元素。當您將 1 加到 b
時,您將得到與將 1 加到 a[:2]
相同的結果。如果您想建立一個新陣列,請使用 numpy.copy
陣列建立常式,如下所示
>>> import numpy as np
>>> a = np.array([1, 2, 3, 4])
>>> b = a[:2].copy()
>>> b += 1
>>> print('a = ', a, 'b = ', b)
a = [1 2 3 4] b = [2 3]
有關更多資訊和範例,請參閱複製與視圖。
有許多常式可以連接現有陣列,例如 numpy.vstack
、numpy.hstack
和 numpy.block
。以下是使用 block
將四個 2x2 陣列連接成一個 4x4 陣列的範例
>>> import numpy as np
>>> A = np.ones((2, 2))
>>> B = np.eye(2, 2)
>>> C = np.zeros((2, 2))
>>> D = np.diag((-3, -4))
>>> np.block([[A, B], [C, D]])
array([[ 1., 1., 1., 0.],
[ 1., 1., 0., 1.],
[ 0., 0., -3., 0.],
[ 0., 0., 0., -4.]])
其他常式使用類似的語法來連接 ndarray。請查看常式的文件以獲取更多範例和語法。
4) 從磁碟讀取陣列,無論是標準或自訂格式#
這是大型陣列建立的最常見情況。細節在很大程度上取決於磁碟上資料的格式。本節提供有關如何處理各種格式的一般指南。有關 IO 的更詳細範例,請參閱如何讀取和寫入檔案。
標準二進制格式#
各個領域都有用於陣列資料的標準格式。以下列出了一些已知的 Python 函式庫可以讀取它們並返回 NumPy 陣列(可能還有其他可以讀取和轉換為 NumPy 陣列的格式,因此也請查看最後一節)
HDF5: h5py
FITS: Astropy
無法直接讀取但轉換起來不難的格式範例是 PIL 等函式庫支援的格式(能夠讀取和寫入許多影像格式,例如 jpg、png 等)。
常見 ASCII 格式#
分隔符號檔案,例如逗號分隔值 (csv) 和 Tab 分隔值 (tsv) 檔案,用於 Excel 和 LabView 等程式。Python 函數可以逐行讀取和解析這些檔案。NumPy 有兩個標準常式用於匯入具有分隔資料的檔案 numpy.loadtxt
和 numpy.genfromtxt
。這些函數在 讀取和寫入檔案 中有更複雜的用例。一個簡單的範例,給定一個 simple.csv
$ cat simple.csv
x, y
0, 0
1, 1
2, 4
3, 9
匯入 simple.csv
是使用 numpy.loadtxt
完成的
>>> import numpy as np
>>> np.loadtxt('simple.csv', delimiter = ',', skiprows = 1)
array([[0., 0.],
[1., 1.],
[2., 4.],
[3., 9.]])
5) 透過使用字串或緩衝區,從原始位元組建立陣列#
可以使用多種方法。如果檔案具有相對簡單的格式,那麼可以編寫一個簡單的 I/O 函式庫,並使用 NumPy 的 fromfile()
函數和 .tofile()
方法直接讀取和寫入 NumPy 陣列(但請注意您的位元組順序!)。如果存在一個好的 C 或 C++ 函式庫可以讀取資料,則可以使用多種技術封裝該函式庫,儘管這肯定需要更多工作,並且需要顯著更進階的知識才能與 C 或 C++ 介接。
6) 使用特殊函式庫函數(例如 SciPy、pandas 和 OpenCV)#
NumPy 是 Python 科學計算堆疊中陣列容器的基礎函式庫。許多 Python 函式庫,包括 SciPy、Pandas 和 OpenCV,都使用 NumPy ndarray 作為資料交換的通用格式。這些函式庫可以建立、操作和使用 NumPy 陣列。