炒雞簡單,帶你快速擼一遍Numpy程式碼!

  • 2019 年 10 月 7 日
  • 筆記

本周目標

  • 初識Numpy
  • ndarray的增刪改查
  • ndarray切片與篩選
  • ndarray運算與排序

NumPy 簡介

NumPyNumerical 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.addnp.substractnp.multiplynp.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進行探索,相信你,一定會愛上這個工具的!