炒雞簡單,帶你快速擼一遍Numpy程式碼!
- 2019 年 10 月 7 日
- 筆記
本周目標
- 初識Numpy
- ndarray的增刪改查
- ndarray切片與篩選
- ndarray運算與排序
NumPy 簡介
NumPy 是 Numerical Python 的簡稱,它是 Python 中的科學計算基本軟體包。NumPy 為 Python 提供了大量數學庫,使我們能夠高效地進行數字計算。更多可點擊Numpy官網(http://www.numpy.org/)查看。
關於Numpy需要知道的幾點:
- NumPy 數組在創建時有固定的大小,不同於Python列表(可以動態增長)。更改ndarray的大小將創建一個新的數組並刪除原始數據。
- NumPy 數組中的元素都需要具有相同的數據類型,因此在存儲器中將具有相同的大小。數組的元素如果也是數組(可以是 Python 的原生 array,也可以是 ndarray)的情況下,則構成了多維數組。
- NumPy 數組便於對大量數據進行高級數學和其他類型的操作。通常,這樣的操作比使用Python的內置序列可能更有效和更少的程式碼執行。
所以,Numpy 的核心是ndarray
對象,這個對象封裝了同質數據類型的n維數組。起名 ndarray
的原因就是因為是 n-dimension-array
的簡寫。接下來本節所有的課程都是圍繞著ndarray來講的,理論知識較少,程式碼量較多,所以大家在學習的時候,多自己動動手,嘗試自己去運行一下程式碼。
創建ndarray
- 由python list創建
# 1維數組 a = np.array([1, 2, 3]) print(type(a), a.shape, a[0], a[1], a[2]) out: <class 'numpy.ndarray'> (3,) 1 2 3 # 重新賦值 a[0] = 5 print(a) out: [5 2 3] # 2維數組 b = np.array([[1,2,3],[4,5,6]]) print(b) out: [[1 2 3] [4 5 6]] print(b[0, 0], b[0, 1], b[1, 0]) out: 1 2 4
- 由numpy內置函數創建
# 創建2x2的全0數組 a = np.zeros((2,2)) print(a) out: [[ 0. 0.] [ 0. 0.]] # 創建1x2的全1數組 b = np.ones((1,2)) print(b) out: [[ 1. 1.]] # 創建2x2定值為7的數組 c = np.full((2,2), 7) print(c) out: [[7 7] [7 7]] # 創建2x2的單位矩陣(對角元素為1) d = np.eye(2) print(d) out: [[ 1. 0.] [ 0. 1.]] #創建一個對角線為10,20,30,50的對角矩陣 d_1 = np.diag([10,20,30,50]) print(d_1) out: [[10 0 0 0] [ 0 20 0 0] [ 0 0 30 0] [ 0 0 0 50]] #創建一個一維的0-14的數組 e = np.arange(15) print(e) out: [ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14] #創建一個一維的4-9的數組 e_1 = np.arange(4,10) print(e_1) out: [4 5 6 7 8 9] #創建一個一維的1-13且以間隔為3的數組 e_2 = np.arange(1,14,3) print(e_2) out: [ 1 4 7 10 13] #創建一個一維的範圍在0-10,長度為6的數組 f = np.linspace(0,10,6) print(f) out: #各個元素的間隔相等,為(10-0)/(6-1) = 2,若不想包含末尾的10,可以添加參數endpoint = False [ 0., 2., 4., 6., 8., 10.] #把arange創建的一維數組轉換為3行4列的二維數組 g = np.arange(12).reshape(3,4) print(g) out: #注意:使用reshape轉換前後的數據量應該相同,12 = 3x4 [[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]] # 2x2的隨機數組(矩陣),取值範圍在[0.0,1.0)(包含0,不包含1) h = np.random.random((2,2)) print(e) out: [[ 0.72776966 0.94164821] [ 0.04652655 0.2316599 ]] #創建一個取值範圍在[4,15),2行2列的隨機整數矩陣 i = np.random.randint(4,15,size = (2,2)) print(i) out: [[6, 5], [5, 9]] #創建一個從均值為0,標準差為0.1的正態分布中隨機抽樣的3x3矩陣 j = np.random.normal(0,0.1,size = (3,3)) print(j) out: [[-0.20783767, -0.12406401, -0.11775284], [ 0.02037018, 0.02898423, -0.02548213], [-0.0149878 , 0.05277648, 0.08332239]]
訪問、刪除、增加ndarray中的元素
這裡主要是提供了一些訪問、更改或增加ndarray中某一元素的基礎方法。
訪問&更改
類似於訪問python list中元素的方式,按照元素的index進行訪問或更改。
#訪問某一元素,這裡可以自己多嘗試 #訪問一維數組的某一元素,中括弧內填寫index print(np.arange(6)[3]) out:3 #訪問二維數組的某一元素,中括弧內填寫[行,列] print(np.arange(6).reshape(3,2)[1,1]) out:3 #訪問三位數組中的某一元素,中括弧內[組,行,列] print(np.arange(12).reshape(2,3,2)[0,1,1]) out:3 #更改某一元素,用 = 進行賦值和替換即可 a = np.arange(6) a[3] = 7 #先訪問,再重新賦值 print(a) [0 1 2 7 4 5]
刪除
可使用np.delete(ndarray, elements, axis)
函數進行刪除操作。
這裡需要注意的是axis
這個參數,在2維數據中,axis = 0
表示選擇行
,axis = 1
表示選擇列
,但不能機械的認為0就表示行,1就表示列,注意前提2維數據中。
在三維數據中,axis = 0表示組,1表示行,2表示列。這是為什麼呢?提示一下,三位數組的shape中組、行和列是怎樣排序的?
所以,axis的賦值一定要考慮數組的shape。
a = np.arange(12).reshape(2,2,3) #思考下,這裡刪除axis = 0下的第0個,會是什麼結果呢?自己試一下 print(np.delete(a,[0],axis = 0))
再有一點需要注意的是,如果你想讓原數據保留刪除後的結果,需要重新賦值一下才可以。
a = np.arange(6).reshape(2,3) np.delete(a,[0],axis = 0) print(a) array([[0, 1, 2], [3, 4, 5]]) #原數據並未更改 a = np.delete(a,[0],axis = 0) #重新賦值 print(a) array([[3, 4, 5]]) #原數據已更改
增加
往ndarray中增加元素的辦法跟python list也很類似,常用的有兩種:
- 一種是添加(append),就是將新增的元素添加到ndarray的尾部
- 語法為:
np.append(ndarray, elements, axis)
- 參數和delete函數一致,用法也一致,這裡不再贅述
- 一種是插入(insert),可以讓新增元素插入到指定位置
- 語法為:
np.insert(ndarray, index, elements, axis)
- 參數中就多了一個
index
,指示的是插入新元素的位置。
這裡值得注意的是,不論是append還是insert,在往多維數組中插入元素時,一定要注意對應axis上的shape要一致。再一個就是,和delete一樣,如果你想要更改原數據,需要重新賦值。
切片和篩選
ndarray切片
前面學了選擇ndarray中的某個元素的方法,這裡我們學習獲取ndarray子集的方法——切片。
對於切片大家並不陌生,在list裡面我們也接觸過切片,一維的ndarray切片與list無異。需要注意的是,就是理解2維及多維ndarray切片。
- 2維矩陣切片
a = np.arange(4*4).reshape(4,4) print(a) out: array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11], [12, 13, 14, 15]]) a[:,:-1] out: array([[ 0, 1, 2], [ 4, 5, 6], [ 8, 9, 10], [12, 13, 14]])
這裡可以看出,我們篩選了a矩陣中前三列的所有行,這是如何實現的呢?
切片的第一個元素:
表示的是選擇所有行,第二個元素:-1
表示的是從第0列至最後一列(不包含),所以結果如上所示。
再看一個例子:
a[1:3,:] out: array([[ 4, 5, 6, 7], [ 8, 9, 10, 11]])
篩選的是第2-3行的所有列。
- 一個常用的切片
以列的形式獲取最後一列數據:
a[:,3:] out: array([[ 3], [ 7], [11], [15]])
以一維數組的形式獲取最後一列數據:
a[:,-1] out: array([ 3, 7, 11, 15])
上面兩種方法經常會用到,前者的shape為(4,1),後者為(4,)。
ndarray篩選
- 選擇ndarray的對角線
所用函數為np.diag(ndarray, k=N)
,其中參數k的取值決定了按照哪一條對角線選擇數據。
默認k = 0,取主對角線;
k = 1時,取主對角線上面1行的元素;
k = -1時,取主對角線下面1行的元素。
思考:這個函數只能選擇主對角線上的元素,那如果想要獲取副對角線上的元素呢?
嘗試自己搜索一下關鍵詞numpy opposite diagonal
尋找答案。
不建議你直接點getting the opposite diagonal of a numpy array。
- 提取ndarray中的唯一值
所用函數為np.unique(ndarray)
,注意unique也可以添加參數axis來控制評判唯一值的軸方向,不好理解可以看示例:
#查看二維數組a中的唯一值 a = [[0,1,2], [3,4,5], [0,1,2]] print(np.unique(a)) array([0, 1, 2, 3, 4, 5]) #查看a中的唯一行(也就是沒有重複的行) print(np.unique(a,axis = 0)) array([[0, 1, 2], [3, 4, 5]]) #查看a中的唯一列 print(np.unique(a,axis = 1)) array([[0, 1, 2], [3, 4, 5], [0, 1, 2]]) #查看a中第一行的唯一值 print(np.unique(a[0])) array([0, 1, 2])
- 通過布爾運算篩選
這裡在中括弧中添加篩選條件,當該條件的結果為True時(即滿足條件時),返回該值。
X[X > 10] #篩選數組X中大於10的數據
這裡需要注意的是,當輸入多個篩選條件時,&
表示與,|
表示或,~
表示非。
運算與排序
ndarray運算
- 集合運算
np.intersect1d(x,y) #取x與y的交集 np.setdiff1d(x,y) #取x與y的差集,返回的是在x中且沒在y中的元素 np.union1d(x,y) #取x與y的並集
- 算術運算
我們可以通過+
、-
、*
、/
或np.add
、np.substract
、np.multiply
、np.divide
來對兩個矩陣進行元素級的加減乘除運算,因為是元素級的運算,所以兩個矩陣的shape必須要一致或者是可廣播(Broadcast)。
這裡所謂的可廣播
,就是指雖然A和B兩個矩陣的shape不一致,但是A可以拆分為整數個與B具有相同shape的矩陣,這樣在進行元素級別的運算時,就會先將A進行拆分,然後與B進行運算,結果再組合一起就可以。這裡的A就是「可廣播」矩陣。
上面涉及到的乘法是元素對應相乘,也就是點乘,那矩陣的叉乘呢?可以了解下numpy.matmul函數。
ndarray排序
我們使用np.sort()
和ndarray.sort()
來對ndarray進行排序。
相同的是:
二者都可以使用參數axis
來決定依照哪個軸進行排序,axis = 0時按照列排序,axis = 1時按照行排序;
不同的是:
np.sort()
不會更改原數組;ndarray.sort()
會更改原數組。
最後
不僅僅是在數據分析中會用到Numpy,之後接觸機器學習、深度學習、影像處理等等,都要跟它打交道,這主要就是因為它豐富的內置函數和快速的響應時間,可以說Numpy支撐起了Python數據科學的半邊天,本文中涉及到的都是偏基礎/常用的知識點,大家在學習/工作中,可以多嘗試搜索Numpy+你想要實現的功能
來對Numpy進行探索,相信你,一定會愛上這個工具的!