Python玩數據 (3):Numpy [2/2]
Posted on May 06, 2017 in CS. View: 4,933
在上一章節的討論,我們已經有了Numpy的基礎概念,在這一篇當中,我們會更深入的了解Numpy還有什麼進階的功能,包括:產生ndarray的多種方法、broadcast的概念以及ndarray的進階操作手法。
產生ndarray的其他方法
在上一章,ndarray的產生方法是由list產生的。
1 |
|
Numpy還提供產生ndarray的其他方式,幫助我們更容易的產生ndarray,譬如,產生一個數列。
1 2 3 4 5 6 7 |
|
stop指的是停止的那點,那點是不包含在產生的數列的。
1D的數列也可轉換成多維度的數列。
1 2 3 4 5 6 7 8 9 10 11 |
|
另外還有一種可以產生連續數列的方法。
1 2 |
|
這個函數是這樣的,0是起始值,2是最終值,這個最終值是包含在數列裡的,9是代表數列會有九個數字,所以它會自動從這區間找九個數字均勻分配。
另外,也可以產生一個全部都零或一的數列,或是矩陣中的「單位矩陣」。
1 2 3 4 5 6 7 8 9 10 11 |
|
或者,你想要亂數產生也可以。
1 2 3 |
|
如果你想要數列依照你給定的規則產生,就先定義好函數,然後再利用fromfunction
製造數列。
1 2 3 4 5 6 |
|
這麼一來,每個位置的值都是由我們所定義的函數所決定。如果你覺得那個func1
名稱很多餘,還有下面這個方法。
1 2 3 4 |
|
上面我使用了lambda
,這個東西稱之為『匿名函數』。
1 |
|
和
1 2 |
|
上面這兩個函式是等價的,差異只在於,第一個函式是沒有名稱的,稱為匿名函數,第二種就是一般的函式,具有名稱。
Broadcasting
在上一章,我有提到一般的矩陣運算,在Numpy中是採用element-wise operation,也就是每個相應元素做運算,然後產生新的ndarray,這個前題是兩組要運算的ndarray他們的shape是相同的,那如果遇到shape不一致,Numpy會怎麼處理呢?實際上,Numpy會幫你把陣列給延伸展開,就像廣播(broadcasting)一樣的傳遞出去,這遵照所謂的broadcasting rules。
1 2 3 4 5 6 7 8 9 |
|
上面就是最普遍的兩個相同shape的矩陣作運算。
那如果是這個情況呢?
1 2 3 4 5 6 7 |
|
你會發現如果矩陣對一個單一元素作運算,其實就等同於這個單一元素對矩陣內的元素分別作運算,這個方式相當好理解,那如果是這樣呢?
1 2 3 4 5 6 7 8 9 10 11 12 |
|
讓我來分解解說一下broadcasting究竟做了什麼,broadcasting能自動填滿矩陣有一個大前提,
參與運算的所有矩陣必須符合以下規則才能做broadcasting,所有矩陣的shape由axis=-1開始對齊去比較彼此間的rank,所有矩陣的在每個axis下的rank必須符合以下兩種規則其中之一:
- 所有rank為同一個值
- 只能有一個矩陣rank為非0或1,其餘矩陣的rank都要為0或1
上面這個例子,在axis= -2之下,只有C矩陣rank具有非0或1的2,而D的rank則為1;在axis= -1之下,只有D矩陣rank具有非0或1的3,而C的rank則為1,因此這兩個陣列可以使用broadcasting rule來延伸。
為什麼我們需要這樣的前提假設,原因是符合這樣的情況下,我們可以藉由重複的複製貼上來使得兩個或多個矩陣有一樣的shape,C矩陣shape為(2,1),所以在axis= -2的方向上,重複貼3次就會產生出shape為(2,3)的矩陣;D矩陣的shape為(1,3),所以在axis= -1的方向上,重複貼2次就會產生出(2,3)的矩陣,如此一來兩個矩陣都是(2,3)就可以作element-wise operation。
逐步示範一下,
1 2 3 4 5 |
|
以下這些都是同樣道理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
我們再來看一下,如果維度不一樣是怎麼運作,譬如說2D碰上3D的,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
分解一下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
|
那這樣的性質可以怎麼運用呢?舉個例子。
1 2 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
Slice and Fancy Indexing
最後,來看一下我們可以怎麼去切ndarray。在python內建語言中,常見的slice是這個樣子
1 2 3 4 5 |
|
那如果是維度再加一級呢?則是這個樣子
1 2 3 4 5 |
|
如果是ndarray,我們常常處理維度大於1的陣列,如果用這個方法來slice,就顯得非常麻煩,Numpy提供了一種比較直覺的方式來做slice。
1 2 3 4 5 6 7 |
|
在中括號裡頭用逗點隔開來表示在各個axis上要取的位置,還可以填入一個陣列來取出一個範圍。
1 2 3 4 5 6 7 8 9 |
|
我們也可以引入一個ndarray來做篩選,常見使用的是布林陣列。
1 2 3 4 5 6 7 8 9 10 |
|
b是由一個邏輯運算產生,這個邏輯運算會對矩陣作element-wise operation,所以會得出一個大小相同的布林陣列。而我們可以將b引入N當作篩選器,把符合的給取出來。事實上還可以更強大的去將取出來的值改值。
1 2 3 4 |
|
上面我將取出來的值加倍,這樣的手法來取值改值會直接影響到原陣列,這是一個很重要的手法。
子彈總結
- 產生ndarray的其他方法:np.arange, np.linspace, np.zeros, np.ones, np.eye, np.random.random 和 np.fromfunction
- Broadcasting的前題:所有矩陣的shape由axis=-1開始對齊去比較彼此間的rank,所有矩陣的在每個axis下的rank必須符合以下兩種規則其中之一:
- 所有rank為同一個值
- 只能有一個矩陣rank為非0或1,其餘矩陣的rank都要為0或1
- Slicing Method ( Ex: M[1,0:2] )
- 布林陣列的取值賦值方法