在昨天的文章中,我們談到了如何合併與分割陣列,在搬運完資料之後,接下來,我們要來看看如何運算這些資料
Universal Function 縮寫為 ufunc,是 NumPy 當中一個強而有力的功能,他能夠針對陣列當中的每一個元素進行快速的計算。
舉個例子,這裡我們先用 x = np.random.randint(0,10,10)
建立一個一維陣列:
[1 0 5 1 9 6 1 9 0 5]
接著,假如要把陣列中的每一個元素都加 10,變成一個新的陣列,這裡我們不需要用 for loop 把每一個元素都抓出來計算。有了 ufunc ,我們可以很簡單的用
x + 10
就可以得到結果
[11 10 15 11 19 16 11 19 10 15]
除了 + 以外,其他的運算也是可以有相同效果:
我們可以做一個小實驗,我們要得到一個新的 array,其元素的值是舊 array 的平方,譬如舊 array = [1,2,3],新 array 就會是 [1,4,9]
這裡我們比較兩種方法,一種是用 for loop 把所有元素抓出來計算
def square(array):
output = np.empty(len(array))
for i in range(len(array)):
output[i] = array[i] ** 2
return output
另外一種是應用 ufunc 的算法如下
array ** 2
另外,我刻意用 np.random.randint(0, 10, 1000000)
創造一個有百萬元素的 array,來凸顯兩者的計算速度差距。你可以在下圖看到計算結果, ufunc 比 for loop 的算法快上了 N 百倍!看到這裡你應該就知道為什麼我們要用 NumPy 來處理資料了吧!
單純針對一個 array 的每一個元素做計算還不厲害,這裡我們也可以直接把兩個 array 抓過來做計算,譬如這裡有兩個 array 分別為
x = np.array([1, 3, 5, 7, 9])
y = np.array([2, 4, 6, 8, 10])
如果直接進行
x * y
會得到有同樣 index 的元素相乘的結果
[2, 12, 30, 56, 90]
這裡要提醒的是,能夠使用 ufunc 做計算的是 numpy array 而不是一般的 Python list 喔,所以上面的例子如果用 x = [1, 3, 5, 7, 9]
是無法作用的。
你可以在下圖看到 numpy array 與 Python list 的不同
當然除了針對陣列元素進行基本的加減乘除之外,ufunc 還有許多數學計算的方法,像是 np.abs()
(取絕對值)、 np.sin()
與其他三角函數系列、np.arcsin()
與其他反三角函數系列 、np.exp()
、np.power()
、np.ln()
、np.log()
等方法,以及統計相關的 np.sum()
、np.mean()
、np.std()
、np.var()
等等方法。
最後來介紹 NumPy 當中的廣播功能。廣播的功能是為了方便不同 shape 的 array 之間進行運算。
譬如現在有兩個 array 分別是 2x3 以及 1x3
#a
[[1. 1. 1.]
[1. 1. 1.]]
#b
[0 1 2]
這時候若要把 array a 和 b 相加,因為兩者的 "shape" 不一樣,因此會先把 b "broadcast" 成
#b
[[0 1 2]
[0 1 2]]
之後,a 與 b 的元素就能一對一對應的相加
若是遇到像下面這樣的情況
#c
[[0]
[1]
[2]]
#d
[0 1]
這時候當我們要做 c + d 時,它就會自動把 c "broadcast" 成
#c
[[0 0]
[1 1]
[2 2]]
把 d "broadcast" 成
#d
[[0 1]
[0 1]
[0 1]]
之後,就能夠順利相加了
下面這張示意圖希望能幫助你更加理解 broadcasting 的機制
連續三天談 NumPy 分別講了
明天開始,我們將會談談另一個重要的 Library: Pandas