《Python Cookbook 3rd》笔记(3.9):大型数组运算
大型數(shù)組運算
問題
你需要在大數(shù)據(jù)集 (比如數(shù)組或網(wǎng)格) 上面執(zhí)行計算。
解法
涉及到數(shù)組的重量級運算操作,可以使用 NumPy 庫。 NumPy 的一個主要特征是它會給 Python 提供一個數(shù)組對象,相比標準的 Python 列表而已更適合用來做數(shù)學運算。下面是一個簡單的小例子,向你展示標準列表對象和 NumPy 數(shù)組對象之間的差別:
>>> # Python lists >>> x = [1, 2, 3, 4] >>> y = [5, 6, 7, 8] >>> x * 2 [1, 2, 3, 4, 1, 2, 3, 4] >>> x + 10 Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: can only concatenate list (not "int") to list >>> x + y [1, 2, 3, 4, 5, 6, 7, 8]>>> # Numpy arrays >>> import numpy as np >>> ax = np.array([1, 2, 3, 4]) >>> ay = np.array([5, 6, 7, 8]) >>> ax * 2 array([2, 4, 6, 8]) >>> ax + 10 array([11, 12, 13, 14]) >>> ax + ay array([ 6, 8, 10, 12]) >>> ax * ay array([ 5, 12, 21, 32]) >>>正如所見,兩種方案中數(shù)組的基本數(shù)學運算結果并不相同。特別的, NumPy 中的標量運算 (比如 ax * 2 或 ax + 10 ) 會作用在每一個元素上。另外,當兩個操作數(shù)都是數(shù)組的時候執(zhí)行元素對等位置計算,并最終生成一個新的數(shù)組。
對整個數(shù)組中所有元素同時執(zhí)行數(shù)學運算可以使得作用在整個數(shù)組上的函數(shù)運算簡單而又快速。比如,如果你想計算多項式的值,可以這樣做:
>>> def f(x): ... return 3*x**2 - 2*x + 7 ... >>> f(ax) array([ 8, 15, 28, 47]) >>>NumPy 還為數(shù)組操作提供了大量的通用函數(shù),這些函數(shù)可以作為 math 模塊中類似函數(shù)的替代。比如:
>>> np.sqrt(ax) array([ 1. , 1.41421356, 1.73205081, 2. ]) >>> np.cos(ax) array([ 0.54030231, -0.41614684, -0.9899925 , -0.65364362]) >>>使用這些通用函數(shù)要比循環(huán)數(shù)組并使用 math 模塊中的函數(shù)執(zhí)行計算要快的多。因此,只要有可能的話盡量選擇 NumPy 的數(shù)組方案。
底層實現(xiàn)中, NumPy 數(shù)組使用了 C 或者 Fortran 語言的機制分配內(nèi)存。也就是說,它們是一個非常大的連續(xù)的并由同類型數(shù)據(jù)組成的內(nèi)存區(qū)域。所以,你可以構造一個比普通 Python 列表大的多的數(shù)組。比如,如果你想構造一個 10,000 * 10,000 的浮點數(shù)二維網(wǎng)格,很輕松:
>>> grid = np.zeros(shape=(10000,10000), dtype=float) >>> grid array([[ 0., 0., 0., ..., 0., 0., 0.],[ 0., 0., 0., ..., 0., 0., 0.],[ 0., 0., 0., ..., 0., 0., 0.],...,[ 0., 0., 0., ..., 0., 0., 0.],[ 0., 0., 0., ..., 0., 0., 0.],[ 0., 0., 0., ..., 0., 0., 0.]]) >>>所有的普通操作還是會同時作用在所有元素上:
>>> grid += 10 >>> grid array([[ 10., 10., 10., ..., 10., 10., 10.],[ 10., 10., 10., ..., 10., 10., 10.],[ 10., 10., 10., ..., 10., 10., 10.],...,[ 10., 10., 10., ..., 10., 10., 10.],[ 10., 10., 10., ..., 10., 10., 10.],[ 10., 10., 10., ..., 10., 10., 10.]]) >>> np.sin(grid) array([[-0.54402111, -0.54402111, -0.54402111, ..., -0.54402111,-0.54402111, -0.54402111],[-0.54402111, -0.54402111, -0.54402111, ..., -0.54402111,-0.54402111, -0.54402111],[-0.54402111, -0.54402111, -0.54402111, ..., -0.54402111,-0.54402111, -0.54402111],...,[-0.54402111, -0.54402111, -0.54402111, ..., -0.54402111,-0.54402111, -0.54402111],[-0.54402111, -0.54402111, -0.54402111, ..., -0.54402111,-0.54402111, -0.54402111],[-0.54402111, -0.54402111, -0.54402111, ..., -0.54402111,-0.54402111, -0.54402111]]) >>>關于 NumPy 有一點需要特別的主意,那就是它擴展 Python 列表的索引功能 - 特別是對于多維數(shù)組。為了說明清楚,先構造一個簡單的二維數(shù)組并試著做些試驗:
>>> a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]) >>> a array([[ 1, 2, 3, 4], [ 5, 6, 7, 8], [ 9, 10, 11, 12]]) >>> # Select row 1 >>> a[1] array([5, 6, 7, 8]) >>> # Select column 1 >>> a[:,1] array([ 2, 6, 10]) >>> # Select a subregion and change it >>> a[1:3, 1:3] array([[ 6, 7], [10, 11]]) >>> a[1:3, 1:3] += 10 >>> a array([[ 1, 2, 3, 4],[ 5, 16, 17, 8],[ 9, 20, 21, 12]]) >>> # Broadcast a row vector across an operation on all rows >>> a + [100, 101, 102, 103] array([[101, 103, 105, 107],[105, 117, 119, 111],[109, 121, 123, 115]]) >>> a array([[ 1, 2, 3, 4],[ 5, 16, 17, 8],[ 9, 20, 21, 12]]) >>> # Conditional assignment on an array >>> np.where(a < 10, a, 10) array([[ 1, 2, 3, 4],[ 5, 10, 10, 8],[ 9, 10, 10, 10]]) >>>討論
NumPy 是 Python 領域中很多科學與工程庫的基礎,同時也是被廣泛使用的最大最復雜的模塊。即便如此,在剛開始的時候通過一些簡單的例子和玩具程序也能幫我們完成一些有趣的事情。
通常我們導入 NumPy 模塊的時候會使用語句 import numpy as np 。這樣的話你就不用再你的程序里面一遍遍的敲入 numpy ,只需要輸入 np 就行了,節(jié)省了不少時間。如果想獲取更多的信息,請查閱 NumPy 官網(wǎng)。
總結
以上是生活随笔為你收集整理的《Python Cookbook 3rd》笔记(3.9):大型数组运算的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux-ubuntu18.04 终端
- 下一篇: 大数据学习(09)--spark学习