numpy基礎(一)

  numpy基礎入門第一部分,介紹了numpy中最重要的數據結構numpy.ndarray的一些基本概念和常用操作。

基本概念

多維數組

numpy中最主要的數據對象就是多維數組,多維數組的緯度稱爲axis。下面例子中的這個數組有兩個維度,第一個維度(axis)的長度(length)爲2,第二個維度的長度爲3

[[1,2,3]
 [4,5,6]]

numpy的數組(array)的數據類型爲ndarray, 和python本身的數組(list)是不同的,python本身的數組(list)只提供了一維的操作,並且不支持對數組進行運算,而numpy的數組提供了更多的功能。

>>> a = np.array([[1,2,3],[4,5,6]])
>>> type(a)
<class 'numpy.ndarray'>

numpy數組(ndarray)的一些重要屬性如下:
以如下數組(ndarray)爲例:

>>> a
array([[[ 11,  22],
        [ 44,  55],
        [ 11,  44]],

       [[ 77,  55],
        [ 44,  55],
        [477,  55]]])

ndarray.ndim

數組的維度數目

>>> a.ndim
3

ndarray.shape

數組每個維度的長度

>>> a.shape
(2, 3, 2)

ndarray.size

數組所有元素的個數

>>> a.size
12

ndarray.dtype

數組中元素的類型,類型可以是python本身的數據類型,也可以是numpy定義的數據類型,比如numpy.int32, numpy.int16, and numpy.float64等等

>>> a.dtype
dtype('int64')

ndarray.itemsize

數組中單個元素佔用的字節數

>>> a.itemsize
8

ndarray.data

數組所在的內存地址,一般不會使用

>>> a.data
<memory at 0x7f67930e69a8>

數組(ndarray)的創建

創建任意的數組

將python的list或者tuple傳入numpy.array()來創建,
可是使用numpy.array()dtype參數來顯示地指定元素類型

# 一維
a = np.array( [1,2,3] )
# 二維
b = np.array( [ [1,2], 
                [3,4], 
                [5,6] ] )
# 三維
c = np.array([ [ [1, 2, 3], 
                 [3 ,4, 5], 
                 [5, 6, 7] ], 
                
               [ [7, 8, 9], 
                 [4, 5, 6], 
                 [3, 2, 1] ] ])


創建指定大小的數組

使用numpy.zeros()來創建一個指定大小(shape)的全零的數組,傳入的參數爲包含每個維度(axis)的長度(length)的tuple, 類似的還可以使用numpy.ones()numpy.empty()創建全1或者未初始化的數組。默認的數據類型(dtype)是float64,可以通過參數dtype指定。

>>> a = np.zeros( (2,3,4) )
>>> a
array([[[0., 0., 0., 0.],
        [0., 0., 0., 0.],
        [0., 0., 0., 0.]],

       [[0., 0., 0., 0.],
        [0., 0., 0., 0.],
        [0., 0., 0., 0.]]])

>>> a = np.empty( (2,3) )
>>> a
array([[2.45126520e-316, 5.72938864e-313, 6.90063282e-310],
       [6.90063282e-310, 0.00000000e+000, 3.39285907e-310]])

>>> a = np.ones( (2,3) )
>>> a
array([[1., 1., 1.],
       [1., 1., 1.]])


使用numpy.random.random()來創建一個指定形狀(shape)的元素爲0-1之間隨機浮點數的數組

>>> np.random.random((5,5))
array([[0.92209695, 0.31994049, 0.82087437, 0.55672011, 0.38671646],
       [0.87978651, 0.16631933, 0.25305667, 0.20991795, 0.27141552],
       [0.65721032, 0.33116113, 0.72580006, 0.24957755, 0.51630277],
       [0.17331517, 0.73900267, 0.41050214, 0.75883384, 0.8719157 ],
       [0.65308589, 0.85678774, 0.77877104, 0.89501972, 0.89551946]])

創建序列數組

numpy.arange

使用numpy.arange()來創建一個一維的序列數組(ndarray),該函數和python的range()類似,產生的數組類型爲ndarray而不是list, 並且支持產生浮現數序列。給numpy.arange()傳入一個參數,則參數結束值;傳入兩個參數,參數按順序爲初始值結束值;傳入三個參數爲,參數按順序爲初始值結束值步長。生成的數組中包含初始值不包含結束值(對整數成立,對浮點數來說由於精度問題可能存在其他情況)。

>>> np.arange(5)
array([0, 1, 2, 3, 4])

>>> np.arange(1,5,1)
array([1, 2, 3, 4])

>>> np.arange(0.1,0.6,0.2)
array([0.1, 0.3, 0.5])


注意:
np.arange()用於生成浮點數時,由於浮點數精度問題得到的序列長度可能是不確定的,可能會多一個或者少一個

>>> a = np.arange(0.1,0.1000005,0.00000001)
>>> a.size
51                  #由於0.00000001無法精確的用二進制表示,這裏多生成了一個數字
>>> a
array([0.1       , 0.10000001, 0.10000002, 0.10000003, 0.10000004,
       0.10000005, 0.10000006, 0.10000007, 0.10000008, 0.10000009,
       0.1000001 , 0.10000011, 0.10000012, 0.10000013, 0.10000014,
       0.10000015, 0.10000016, 0.10000017, 0.10000018, 0.10000019,
       0.1000002 , 0.10000021, 0.10000022, 0.10000023, 0.10000024,
       0.10000025, 0.10000026, 0.10000027, 0.10000028, 0.10000029,
       0.1000003 , 0.10000031, 0.10000032, 0.10000033, 0.10000034,
       0.10000035, 0.10000036, 0.10000037, 0.10000038, 0.10000039,
       0.1000004 , 0.10000041, 0.10000042, 0.10000043, 0.10000044,
       0.10000045, 0.10000046, 0.10000047, 0.10000048, 0.10000049,
       0.1000005 ]) #好像0.1000005也被加進去了,其實並不是
>>> b = a[50]
>>> b == 0.1000005
False
>>> b - 0.1000005
-2.636779683484747e-16 #由於0.00000001存在誤差,在加了50次後得到的值略小於0.1000005


numpy.linspace

爲了創建指定區間包含指定元素個數的數組,可以使用numpy.linspace(),該函數會根據指定的區間和元素個數自動決定步長。
該函數參數爲起始值結束值元素個數,其中起始值結束值都會包含在生成的數組中
numpy.linspace()默認數據類型爲float64

>>> a = np.linspace(0.1, 0.1000005, 50)
>>> a
array([0.1       , 0.10000001, 0.10000002, 0.10000003, 0.10000004,
       0.10000005, 0.10000006, 0.10000007, 0.10000008, 0.10000009,
       0.1000001 , 0.10000011, 0.10000012, 0.10000013, 0.10000014,
       0.10000015, 0.10000016, 0.10000017, 0.10000018, 0.10000019,
       0.1000002 , 0.10000021, 0.10000022, 0.10000023, 0.10000024, #後面的是跳過了一個數0.10000025
       0.10000026, 0.10000027, 0.10000028, 0.10000029, 0.1000003 , 
       0.10000031, 0.10000032, 0.10000033, 0.10000034, 0.10000035,
       0.10000036, 0.10000037, 0.10000038, 0.10000039, 0.1000004 ,
       0.10000041, 0.10000042, 0.10000043, 0.10000044, 0.10000045,
       0.10000046, 0.10000047, 0.10000048, 0.10000049, 0.1000005 ])

# 如果指定的類型爲整數,根據要求生成的數組個數計算出的步長爲小數時,linspace()會把生成數組中對應小數取整得到整數數組
>>> a = np.linspace(1, 8, 6,dtype=np.int64)
>>> a
array([1, 2, 3, 5, 6, 8])
>>> a = np.linspace(1, 8, 6)
>>> a
array([1. , 2.4, 3.8, 5.2, 6.6, 8. ])


其他方式創建數組

numpy.fromfunction

該函數基本參數爲用於生成數組元素的函數數組的大小(shape),可以使用dtype指定數組元素的類型,默認類型是float64。該函數會把每個數組元素的索引值傳給用於生成數組元素的函數,將該函數的返回值作爲元素的值。

>>> def f(a,b):
...     return a+b
... 
>>> b = np.fromfunction(f, (3,3))
>>> b
array([[0., 1., 2.],
       [1., 2., 3.],
       [2., 3., 4.]])


基本操作

算數運算會作用到數組的每一個元素上,然後生成一個新的數組

普通算數運算

>>> a = np.array([[1,2],
                  [3,4]])
>>> b = np.array([[5,6],
                  [7,8]])
# 加法
>>> c = a+b
>>> c
array([[ 6,  8],
       [10, 12]])
# 乘法
>>> c = a * b
>>> c
array([[ 5, 12],
       [21, 32]])


矩陣乘法

(還是上例的a和b)使用@運算符或者ndarry.dot()方法

>>> c = a@b
>>> c
array([[19, 22],
       [43, 50]])
>>> c = a.dot(b)
>>> c
array([[19, 22],
       [43, 50]])


注意:不同類型(int64,int32,float64…)的數組進行運算時,會自動進行類型轉換,將類型統一爲表示範圍更大的類型

一些有用的方法

名稱 作用
ndarray.min 求數組中所有元素的最小值,或者指定某一個維度(axis)的最小值
ndarray.max 求數組中所有元素的最大值,或者指定某一個維度(axis)的最小值
ndarray.sum 求數組中所有元素的和,或者指定某一個維度(axis)的最小值
ndarray.cumsum 求數組中所有元素的累計和(a1, a1+a2, a1+a2+a3…),或者指定某一個維度(axis)的累積和
numpy.exp 計算e爲底數,數組中每個數作爲指數的冪
numpy.sqrt 計算數組中每個數的平方根
numpy.sin 計算數組中每個數的正弦值
numpy.cos 計算數組中每個數的餘弦值

數組的訪問,切分和遍歷

訪問單個元素

數組(ndarray)的訪問使用類似a[<index1>, <index2>, <index3>]或者a[<index1>][<index2>][index3]的形式來訪問, 索引值從0開始,也可以使用負數來表示倒序的索引值,負數索引從-1開始

>>> a = np.array([[1,2],[3,4]])
>>> a
array([[1, 2],
       [3, 4]])
>>> a[1,1]
4
>>> a[0,1]
2
>>> a[-1,-1]
4
>>> a[1][1]
4

切片訪問

使用[<start> : <end>]來表示對範圍元素的訪問,即數組的切片,範圍中包括<start>包括<end>。如果省略<start>或者<end>分別表示從第一個元素開始以及直到最後一個元素(包括最後一個元素)。
此外還可以使用...來表示選取除了指定部分之外的全部元素, 例如,若x是5維數組, 那麼

  1. x[1,2,…]等價於x[1,2,:,:,:]
  2. x[…,3]等價於x[:,:,:,:,3]
  3. x[4,…,5,:]等價於x[4,:,:,5,:]

注意:使用了...後即使訪問範圍只有一個元素也會返回數組類型(ndarray)

>>> a = np.fromfunction(f,(5,5), dtype=int)
>>> a
array([[0, 1, 2, 3, 4],
       [1, 2, 3, 4, 5],
       [2, 3, 4, 5, 6],
       [3, 4, 5, 6, 7],
       [4, 5, 6, 7, 8]])
>>> a[...]
array([[0, 1, 2, 3, 4],
       [1, 2, 3, 4, 5],
       [2, 3, 4, 5, 6],
       [3, 4, 5, 6, 7],
       [4, 5, 6, 7, 8]])
>>> a[1,...,1]
array(2)
>>> a[1:3,1:3]
array([[2, 3],
       [3, 4]])
>>> a[1:3,...]
array([[1, 2, 3, 4, 5],
       [2, 3, 4, 5, 6]])

遍歷數組

假設有三維數組a,可以直接使用for遍歷a,循環的次數爲第一個維度(axis)的長度(length)

# 生成三維數組
>>> a = np.fromfunction(lambda x,y,z:x+y+z, (3, 3, 3), dtype=int)
>>> a
array([[[0, 1, 2],
        [1, 2, 3],
        [2, 3, 4]],

       [[1, 2, 3],
        [2, 3, 4],
        [3, 4, 5]],

       [[2, 3, 4],
        [3, 4, 5],
        [4, 5, 6]]])
>>> for i in a:
...     print(i)
... 
[[0 1 2]
 [1 2 3]
 [2 3 4]]
[[1 2 3]
 [2 3 4]
 [3 4 5]]
[[2 3 4]
 [3 4 5]
 [4 5 6]]

還可以使用for循環遍歷a.flat, 這樣會遍歷到a中的每個元素,循環次數爲a中元素的個數(size)

# 還是上個例子中的數組a
>>> for i in a.flat:
...     print(i,end=" ")
... 
0 1 2 1 2 3 2 3 4 1 2 3 2 3 4 3 4 5 2 3 4 3 4 5 4 5 6 


調整數組形狀(shape)

函數 作用
ndarray.ravel 利用原數組生成對應的一維數組
ndarray.reshape 利用原數組生成指定形狀(shape)的數組
ndarray.T 生成原數組的轉置

以上函數不改變原數組

函數 作用
ndarray.resize 改變原數組的形狀(shape)
>>> a = np.floor( np.random.random((2,3)) * 10)
>>> a
array([[5., 9., 5.],
       [1., 7., 3.]])
>>> a.ravel()
array([5., 9., 5., 1., 7., 3.])
>>> a.reshape(3,2)
array([[5., 9.],
       [5., 1.],
       [7., 3.]])
>>> a.T
array([[5., 1.],
       [9., 7.],
       [5., 3.]])
# 不改變a
>>> a
array([[5., 9., 5.],
       [1., 7., 3.]])
# 改變a
>>> a.resize(3,2)
>>> a
array([[5., 9.],
       [5., 1.],
       [7., 3.]])


注意:轉置和ndarray.reshape生成同樣形狀的數組時生成規則是不一樣的,轉置會把第二個維度作爲第一個維度,把第一個維度作爲第二個維度,而利用reshape生成同樣形狀的數組時並不做維度交換,具體的區別請看上述例子。

數組的合併

numpy.vstack & numpy.row_stack

這兩個函數的作用是一樣的,將數組在第一個維度上合併。

說明:官方文檔中並沒有numpy.row_stack文檔,只有numpy.ma.row_stack,不過numpy.row_stack確實是可以調用的,在python中輸入help(numpy.row_stack)會跳轉到numpy.vstack的說明文檔,因此numpy.row_stack可能只是numpy.vstack的一個別名。

關於numpy.ma是什麼,參見numpy.ma

>>> a
array([[0., 1., 2.],
       [1., 2., 3.]])
>>> b
array([[0., 1., 2.],
       [2., 3., 4.]])
>>> np.vstack( (a,b) )
array([[0., 1., 2.],
       [1., 2., 3.],
       [0., 1., 2.],
       [2., 3., 4.]])
>>> np.row_stack( (a,b) )
array([[0., 1., 2.],
       [1., 2., 3.],
       [0., 1., 2.],
       [2., 3., 4.]])

numpy.hstack

將數組在第二個維度合併

# 使用上個例子中的a和b
>>> np.hstack((a,b))
array([[0., 1., 2., 0., 1., 2.],
       [1., 2., 3., 2., 3., 4.]])
>>> 

注意:如果數組沒有第二個維度(一維數組),則合併第一個維度

>>> a
array([1, 2])
>>> b
array([3, 4])
>>> np.hstack((a,b))
array([1, 2, 3, 4])

numpy.column_stack

將數組在第二個維度上合併(該方法一般用來將一維數組作爲列合併成二維數組,見注意部分)

詳細函數說明請參考numpy.column_stack

>>> a
array([[0., 1.],
       [1., 2.]])
>>> b
array([[3., 4.],
       [4., 5.]])
>>> np.column_stack((a,b))
array([[0., 1., 3., 4.],
       [1., 2., 4., 5.]])


注意:如果數組沒有第二個維度(一維數組),則將原數組轉置爲2維列向量然後合併

>>> a
array([1, 2])
>>> b
array([3, 4])
>>> np.column_stack((a,b))
array([[1, 3],
       [2, 4]])

numpy.column_stacknumpy.hstack只有在處理一維數組上存在上述差異,其他維度是相同的,下面是3維數組的一個測試

>>> bb = np.fromfunction(lambda x,y,z:50+x+y+z,(2,2,2))
>>> aa = np.fromfunction(lambda x,y,z:1+x+y+z,(2,2,2))
>>> aa
array([[[1., 2.],
        [2., 3.]],

       [[2., 3.],
        [3., 4.]]])
>>> bb
array([[[50., 51.],
        [51., 52.]],

       [[51., 52.],
        [52., 53.]]])
>>> np.hstack((aa,bb))
array([[[ 1.,  2.],
        [ 2.,  3.],
        [50., 51.],
        [51., 52.]],

       [[ 2.,  3.],
        [ 3.,  4.],
        [51., 52.],
        [52., 53.]]])
>>> np.column_stack((aa,bb))
array([[[ 1.,  2.],
        [ 2.,  3.],
        [50., 51.],
        [51., 52.]],

       [[ 2.,  3.],
        [ 3.,  4.],
        [51., 52.],
        [52., 53.]]])


numpy.concatenate

該函數將數組在參數axis指定的維度上合併

詳細函數說明請參考numpy.concatenate

>>> aa
array([[[1., 2.],
        [2., 3.]],

       [[2., 3.],
        [3., 4.]]])
>>> bb
array([[[50., 51.],
        [51., 52.]],

       [[51., 52.],
        [52., 53.]]])
>>> np.concatenate((aa,bb), axis=2)
array([[[ 1.,  2., 50., 51.],
        [ 2.,  3., 51., 52.]],

       [[ 2.,  3., 51., 52.],
        [ 3.,  4., 52., 53.]]])
>>> np.concatenate((aa,bb), axis=1)
array([[[ 1.,  2.],
        [ 2.,  3.],
        [50., 51.],
        [51., 52.]],

       [[ 2.,  3.],
        [ 3.,  4.],
        [51., 52.],
        [52., 53.]]])
>>> np.concatenate((aa,bb), axis=0)
array([[[ 1.,  2.],
        [ 2.,  3.]],

       [[ 2.,  3.],
        [ 3.,  4.]],

       [[50., 51.],
        [51., 52.]],

       [[51., 52.],
        [52., 53.]]])


參考資料

numpy tutorial

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章