2018年12月2日 星期日

NumPy 筆記:陣列 ndarray

前言


NumPy 是 Python 的運算套件,提供陣列 (ndarray)、矩陣 (matrix)……等常用的數學工具,運算速度比 Python 內建的資料格式快很多。NumPy 已經將許多常用的運算寫成函式,如果能善用這些函式,可以大幅加快程式的運算速度。以下是一些我目前常用到的陣列相關函式整理,如果之後有用到新的函式會再新增內容。請注意,以下的程式碼都省略了 import numpy as np




產生陣列


手動輸入


一維陣列語法

np.array([元素1, 元素2, 元素3, 元素4, 元素5], dtype = 格式)

二維陣列語法

np.array([(元素11, 元素12, 元素13, 元素14, 元素15), (元素21, 元素22, 元素23, 元素24, 元素25)], dtype = 格式)

數值格式可以是 整數 (int)、浮點數 (float)、複數 (complex),如果不指定的話系統會自動判斷。
範例:

in[1]:  np.array([1, 2, 3, 4, 5])
out[1]: array([1, 2, 3, 4, 5])
in[2]:  np.array([1, 2, 3, 4, 5], dtype = float)
out[2]: array([1., 2., 3., 4., 5.])
in[3]:  np.array([1, 2, 3, 4, 5], dtype = complex)
out[3]: array([1.+0.j, 2.+0.j, 3.+0.j, 4.+0.j, 5.+0.j])
in[4]:  np.array([(1, 2, 3, 4, 5), (6, 7, 8, 9, 10)], dtype = int)
out[4]: array([[ 1,  2,  3,  4,  5],
               [ 6,  7,  8,  9, 10]])




np.dtype


功能:取得資料格式
假設陣列A為 array([1, 2, 3, 4, 5]),如果想要知道資料的格式,可以使用
in[1]:  A.dtype
out[1]: dtype('int64')



取得陣列長度或維度


假設陣列A為 array([1, 2, 3, 4, 5]),如果想要知道陣列A的長度,可以使用

in[1]:  len(A)
out[1]: 5

假設陣列B為 array([[ 1, 2, 3, 4, 5], [ 6, 7, 8, 9, 10]]),維度為(2, 5),如果想要知道陣列B的維度,可以使用

in[2]:  B.shape
out[2]: (2, 5)

如果使用以下的寫法,回傳的數值是列數。

in[3]:  len(B)
out[3]: 2

如果使用以下的寫法,回傳的數值是第0列裡的元素數量。

in[4]:  len(B[0])
out[4]: 5




np.zeros


功能:產生指定長度的一維陣列,每個元素皆為0。
語法

np.zeros(長度)

範例:

in[1]:  np.zeros(10)
out[1]: array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])



np.ones


功能:產生指定長度的一維陣列,每個元素皆為1。
語法

np.ones(長度)

範例:

in[1]:  np.ones(10)
out[1]: array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])



np.arange


功能:產生一維陣列,第一個元素為起始值,下一個元素為這個元素加上間隔,不包含結束值。起始值預設為0,間隔預設為1。
語法:

np.arange(起始值, 結束值, 間隔)

範例:

in[1]:  np.arange(10)
out[1]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
in[2]:  np.arange(1, 10)
out[2]: array([1, 2, 3, 4, 5, 6, 7, 8, 9])
in[3]:  np.arange(1, 10, 2)
out[3]: array([1, 3, 5, 7, 9])



np.linspace


功能:產生一維陣列,第一個元素為起始值,最後一個元素為結束值,將兩者之間均勻分割為指定的數量-1。
語法:

np.linspace(起始值, 結束值, 數量)

範例:

in[1]:  np.linspace(0, 1, 11)
out[1]: array([0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1. ])




操作陣列


取出元素值


陣列的的索引值 (index) 從0開始,假設陣列A為array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),取出索引值為3的元素,語法為

in[1]:  A[3]
out[1]: 3

取出索引值為3到7的元素,語法為

in[2]:  A[3:8]
out[2]: array([3, 4, 5, 6, 7])

取出索引值為0到倒數第3個元素,語法為

in[3]:  A[:-2]
out[3]: array([0, 1, 2, 3, 4, 5, 6, 7])

取出最後1個元素,語法為

in[4]:  A[-1]
out[4]: 9

反方向取出所有的元素,語法為

in[5]:  A[::-1]
out[5]: array([9, 8, 7, 6, 5, 4, 3, 2, 1, 0])



四則運算


假設陣列A為 array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),可以一次將所有的元素同時加、減、乘、除,語法為

in[1]:  A + 1
out[1]: array([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10])
in[2]:  A - 1
out[2]: array([-1,  0,  1,  2,  3,  4,  5,  6,  7,  8])
in[3]:  A * 2
out[3]: array([ 0,  2,  4,  6,  8, 10, 12, 14, 16, 18])
in[4]:  A / 2
out[4]: array([0. , 0.5, 1. , 1.5, 2. , 2.5, 3. , 3.5, 4. , 4.5])

假設陣列B為 array([10, 11, 12, 13, 14, 15, 16, 17, 18, 19]),可以一次將兩個陣列中所有的元素同時加、減、乘、除,語法為

in[5]:  A + B
out[5]: array([10, 12, 14, 16, 18, 20, 22, 24, 26, 28])
in[6]:  A - B
out[6]: array([-10, -10, -10, -10, -10, -10, -10, -10, -10, -10])
in[7]:  A * B
out[7]: array([  0,  11,  24,  39,  56,  75,  96, 119, 144, 171])
in[8]:  A / B
out[8]: array([0.        , 0.09090909, 0.16666667, 0.23076923, 0.28571429,
               0.33333333, 0.375     , 0.41176471, 0.44444444, 0.47368421])



np.sum


功能:將陣列中所有元素的值相加。
語法:

np.sum(陣列名稱)

假設陣列A為 array([1, 2, 3, 4, 5]),則語法為

in[1]:  np.sum(A)
out[1]: 15



np.min


功能:找出陣列中所有元素的最小值。
語法:

np.min(陣列名稱)

假設陣列A為 array([1, 2, 3, 4, 5]),則語法為

in[1]:  np.min(A)
out[1]: 1



np.max


功能:找出陣列中所有元素的最大值。
語法:

np.max(陣列名稱)

假設陣列A為 array([1, 2, 3, 4, 5]),則語法為

in[1]:  np.max(A)
out[1]: 5



np.diff


功能:將陣列下一個元素與這一個元素相減。
語法:

np.diff(陣列名稱)

假設陣列A為 array([1, 2, 4, 7, 11, 16]),則語法為

in[1]:  np.diff(A)
out[1]: array([1, 2, 3, 4, 5])

如果想要用 Python 內建的串列 (list) 格式做到相同的效果,需要使用以下的寫法

B = [1, 2, 4, 7, 11, 16]
C = []
for i in range(len(B) - 1):
    C.append(B[i+1] - B[i])
print(C)



np.clip


功能:將陣列中所有元素的值限制在指定的範圍內。
語法:

np.clip(最小值, 最大值)

假設陣列A為 array([0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1. ]),如果要將元素值限制在 0.3 和 0.8 之間,則語法為

in[1]:  A.clip(0.3, 0.8)
out[1]: array([0.3, 0.3, 0.3, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.8, 0.8])



np.where


功能:回傳陣列當中符合條件的元素索引值。
語法:

np.where(陣列及條件)

假設陣列A為 array([ 0, 2, 4, 6, 8, 10]),如果要找所有大於5的元素索引值,則語法為

in[1]:  np.where(A > 5)
out[1]: (array([3, 4, 5]),)

我們可以把回傳值傳給另一個陣列,假設陣列B為 array([10, 12, 14, 16, 18, 20]),如果想要取出符合 A > 5 對應的元素,則語法為

in[2]:  B[np.where(A > 5)]
out[2]: array([16, 18, 20])



np.reshape


功能:將陣列改變成指定的維度,可以到3個以上的維度,但是這樣很難想像陣列的樣子,我通常只用到二維陣列。
語法:

np.reshape(維度1, 維度2)

假設陣列A為 array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),如果要將陣列維度改為(2, 5),語法為

in[1]:  A.reshap(2, 5)
out[1]: array([[0, 1, 2, 3, 4],
               [5, 6, 7, 8, 9]])

也可以將產生陣列以及改變維度兩件事一起完成,語法為

in[2]:  np.arange(10).reshape(2, 5)
out[2]: array([[0, 1, 2, 3, 4],
               [5, 6, 7, 8, 9]])



np.T


功能:將陣列中的元素行、列對調,通常會接在陣列物件之後。
假設陣列A為 array([[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]]),若要將陣列轉置,語法為:

in[1]:  A.T
out[1]: array([[0, 5],
               [1, 6],
               [2, 7],
               [3, 8],
               [4, 9]])



np.vstack


功能:將陣列以垂直方向疊合。
假設陣列A為 array([0, 1, 2, 3, 4])、陣列B為 array([5, 6, 7, 8, 9]),若要將陣列以垂直方向疊合,語法為:

in[1]:  np.vstack((A, B))
out[1]: array([[0, 1, 2, 3, 4],
               [5, 6, 7, 8, 9]])

另外還有兩個功能很類似的函式:np.stack、np.hstack,有興趣的同學可以上網搜尋使用說明。



np.meshgrid


功能:將兩個一維陣列交錯組合成二維陣列。
範例

x = np.arange(-2, 3, 1)
y = np.arange(-2, 3, 1)
xv, yv = np.meshgrid(x, y)
print("xv:", xv)
print("yv:", yv)

輸出為

xv: [[-2 -1  0  1  2]
     [-2 -1  0  1  2]
     [-2 -1  0  1  2]
     [-2 -1  0  1  2]
     [-2 -1  0  1  2]]
yv: [[-2 -2 -2 -2 -2]
     [-1 -1 -1 -1 -1]
     [ 0  0  0  0  0]
     [ 1  1  1  1  1]
     [ 2  2  2  2  2]]

如果將程式碼改為

 xx, yy = np.meshgrid(x, y, sparse = True)
print("xx:", xx)
print("yy:", yy)

輸出會變為

xx: [[-2 -1  0  1  2]]
yy: [[-2]
     [-1]
     [ 0]
     [ 1]
     [ 2]]




結語


NumPy 內建相當多方便的函式,如果能夠善用這些函式,可以大幅提升程式運作的效率。




HackMD 版本連結:https://hackmd.io/s/BytGou11E

沒有留言:

張貼留言