用人話說 Numpy – 2/13 陣列Array
NumPy 的主要特色就是 array 物件類別。陣列類似於 Python 的列表 list ,除了陣列內的每個元素都要是相同的類型,通常是整數 int 或是浮點數 float 。陣列使得操作巨大的數值可以很快速,並且比 list 更有效率。
陣列可以從 list 建立
- >>> a = np.array([1, 4, 5, 8], float)
- >>> a
- array([ 1., 4., 5., 8.])
- >>> type(a)
- <type 'numpy.ndarray'>
這裡的 array 函數接收了兩個參數:第一個是要轉換成陣列的列表,第二個是每一個成員的類型。陣列的元素是可以訪問的,可以切片的,可以操作的。
- >>> a[:2]
- array([ 1., 4.])
- >>> a[3]
- 8.0
- >>> a[0] = 5.
- >>> a
- array([ 5., 4., 5., 8.])
陣列可以是多維的。跟列表不同,陣列的不同維度用逗號在括號內分隔。以下是一個二維陣列(也叫矩陣)的範例
- >>> a = np.array([[1, 2, 3], [4, 5, 6]], float)
- >>> a
- array([[ 1., 2., 3.],
- [ 4., 5., 6.]])
- >>> a[0,0]
- 1.0
- >>> a[0,1]
- 2.0
陣列的切片在操作多維的陣列時跟處理一般陣列時一樣,陣列像是通過一個過濾器一樣,使過濾後的每個切片都是指定規範的維度。使用符號”:”
在一個維度上過濾該維度的所有內容
- >>> a = np.array([[1, 2, 3], [4, 5, 6]], float)
- >>> a[1,:]
- array([ 4., 5., 6.])
- >>> a[:,2]
- array([ 3., 6.])
- >>> a[-1:,-2:]
- array([[ 5., 6.]])
屬性 shape 會返回陣列的每一維的數量,返回的型態是 tuple 。
- >>> a.shape
- (2, 3)
屬性 dtype 返回陣列內的類型
- >>> a.dtype
- dtype('float64')
這裡顯示的 float64 是數值類型,NumPy 用來存放雙精度(8-byte)的實數,像是 Python 裡的 float 類型。
當函數 len 用在陣列時,會返回第一個維度的長度(數量)
- >>> a = np.array([[1, 2, 3], [4, 5, 6]], float)
- >>> len(a)
- 2
使用 in 語句,可以用來測試一個值是不是存在陣列之內
- >>> a = np.array([[1, 2, 3], [4, 5, 6]], float)
- >>> 2 in a
- True
- >>> 0 in a
- False
陣列可以用 reshape 方法,以 tuple 做為參數轉換成新的維度。在接下來的範例,把10個元素的一維陣列轉換成二維陣列第一個維度有五個元素,第二個維度有兩個元素
- >>> a = np.array(range(10), float)
- >>> a
- array([ 0., 1., 2., 3., 4., 5., 6., 7., 8., 9.])
- >>> a = a.reshape((5, 2))
- >>> a
- array([[ 0., 1.],
- [ 2., 3.],
- [ 4., 5.],
- [ 6., 7.],
- [ 8., 9.]])
- >>> a.shape
- (5, 2)
這裡注意 reshape 函數是建立一個新的陣列,而不是修改原始的陣列。
記得 Python 的名稱綁定方式仍然作用於陣列。copy 方法可以用來建立一個新的陣列,如果需要
可以在記憶體內分離複本。
- >>> a = np.array([1, 2, 3], float)
- >>> b = a
- >>> c = a.copy()
- >>> a[0] = 0
- >>> a
- array([0., 2., 3.])
- >>> b
- array([0., 2., 3.])
- >>> c
- array([1., 2., 3.])
可以從陣列建立列表
- >>> a = np.array([1, 2, 3], float)
- >>> a.tolist()
- [1.0, 2.0, 3.0]
- >>> list(a)
- [1.0, 2.0, 3.0]
- >>> z = a.tolist()
- >>> z
- [0.0, 2.0, 3.0]
- >>> type(z)
- <class 'list'>
- >>> y = list(a)
- >>> y
- [0.0, 2.0, 3.0]
- >>> type(y)
- <class 'list'>
使用 tostring 方法可以把陣列內的原始資料轉換成二進制字串(不是人類可讀的格式)。fromstring 方法可以用這個二進制的數據建立陣列。這些方法對儲存大量數據到檔案來說很方便。
- >>> a = array([1, 2, 3], float)
- >>> s = a.tostring()
- >>> s
- '\x00\x00\x00\x00\x00\x00\xf0?\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x00
- \x00\x00\x08@'
- >>> np.fromstring(s)
- array([ 1., 2., 3.])
補充:
.tostring 方法即將被棄用,改名為 .tobytes() 用法及結果都是一樣的
fill 方法可以把陣列填入指定的值。
- >>> a = array([1, 2, 3], float)
- >>> a
- array([ 1., 2., 3.])
- >>> a.fill(0)
- >>> a
- array([ 0., 0., 0.])
陣列的 transpose 方法可以生成陣列的轉置陣列,會生成兩個維度對調的新陣列
- >>> a = np.array(range(6), float).reshape((2, 3))
- >>> a
- array([[ 0., 1., 2.],
- [ 3., 4., 5.]])
- >>> a.transpose()
- array([[ 0., 3.],
- [ 1., 4.],
- [ 2., 5.]])
多維陣列可以使用 flatten()方法,產生新的一維陣列
- >>> a = np.array([[1, 2, 3], [4, 5, 6]], float)
- >>> a
- array([[ 1., 2., 3.],
- [ 4., 5., 6.]])
- >>> a.flatten()
- array([ 1., 2., 3., 4., 5., 6.])
兩個以上的陣列,可以使用 concatenate 函數,使用 tuple格式的參數將陣列聯集起來
- >>> a = np.array([1,2], float)
- >>> b = np.array([3,4,5,6], float)
- >>> c = np.array([7,8,9], float)
- >>> np.concatenate((a, b, c))
- array([1., 2., 3., 4., 5., 6., 7., 8., 9.])
如果陣列是多於一維陣列,可以透過指定維度來聯集多維陣列,如果沒有指定維度,NumPy 預設用第一個維度
- >>> a = np.array([[1, 2], [3, 4]], float)
- >>> b = np.array([[5, 6], [7,8]], float)
- >>> np.concatenate((a,b))
- array([[ 1., 2.],
- [ 3., 4.],
- [ 5., 6.],
- [ 7., 8.]])
- >>> np.concatenate((a,b), axis=0)
- array([[ 1., 2.],
- [ 3., 4.],
- [ 5., 6.],
- [ 7., 8.]])
- >>> np.concatenate((a,b), axis=1)
- array([[ 1., 2., 5., 6.],
- [ 3., 4., 7., 8.]])
陣列的維度可以用括號中的 newaxis 常數來增加維度
- >>> a = np.array([1, 2, 3], float)
- >>> a
- array([1., 2., 3.])
- >>> a[:,np.newaxis]
- array([[ 1.],
- [ 2.],
- [ 3.]])
- >>> a[:,np.newaxis].shape
- (3,1)
- >>> b[np.newaxis,:]
- array([[ 1., 2., 3.]])
- >>> b[np.newaxis,:].shape
- (1,3)
這裡的範例都是二維的,其中用 np.newaxis 建立的陣列,長度為1。使用 newxis 方式建立陣列,對於向量跟矩陣的數學計算來說很方便。