- Python進階編程:編寫更高效、優雅的Python代碼
- 劉宇宙 謝東 劉艷
- 1248字
- 2021-04-30 12:39:35
1.4.5 大型數組運算
在實際應用中,我們經常需要在大數據集(比如數組或網格)上執行運算。
涉及數組的重量級運算,可以使用NumPy庫。NumPy庫的一個主要特征是它會給Python提供一個數組對象,其相比于標準的Python列表而言更適合用來做數學運算。下面通過示例查看標準的Python列表對象和NumPy庫中的數組對象之間的使用差別:
x = [1, 2, 3, 4] y = [5, 6, 7, 8] print(f'{x} * 2 is: {x * 2}') # print(x + 10) print(f'{x} + {y} = {x + y}') import numpy as np ax = np.array([1, 2, 3, 4]) ay = np.array([5, 6, 7, 8]) print(f'{ax} * 2 = {ax * 2}') print(f'{ax} + 10 = {ax + 10}') print(f'{ax} + {ay} = {ax + ay}') print(f'{ax} * {ay} = {ax * ay}')
執行py文件,輸出結果如下:
[1, 2, 3, 4] * 2 is: [1, 2, 3, 4, 1, 2, 3, 4] [1, 2, 3, 4] + [5, 6, 7, 8] = [1, 2, 3, 4, 5, 6, 7, 8] [1 2 3 4] * 2 = [2 4 6 8] [1 2 3 4] + 10 = [11 12 13 14] [1 2 3 4] + [5 6 7 8] = [6 8 10 12] [1 2 3 4] * [5 6 7 8] = [5 12 21 32]
兩種方案中數組的基本數學運算結果并不相同。NumPy庫中的標量運算(如ax*2或ax+10)會作用在每一個元素上。當兩個操作數都是數組的時候,執行元素對等位置計算,并最終生成一個新的數組。
對整個數組中的所有元素同時執行數學運算,可以使得作用在整個數組上的函數運算簡單又快速。計算多項式的值的示例如下:
def f(px): return 3 * px ** 2 - 2 * px + 7 print(f'f(ax) = {f(ax)}')
執行py文件,輸出結果如下:
f(ax) = [ 8 15 28 47]
NumPy還為數組操作提供了大量的通用函數,這些函數可以作為math模塊中類似函數的替代,示例如下:
print(f'np.sqrt({ax}) = {np.sqrt(ax)}') print(f'np.cos({ax}) = {np.cos(ax)}')
執行py文件,輸出結果如下:
np.sqrt([1 2 3 4]) = [1. 1.41421356 1.73205081 2. ] np.cos([1 2 3 4]) = [0.54030231 -0.41614684 -0.9899925 -0.65364362]
使用這些通用函數要比循環數組并使用math模塊中的函數執行計算快得多,因此應盡量選擇NumPy的數組方案。
在底層實現中,NumPy數組使用了C或者Fortran語言的機制分配內存。也就是說,NumPy是一個非常大、連續并由同類型數據組成的內存區域,所以可以構造一個比普通Python列表大得多的數組。如構造一個10 000×10 000的浮點數二維網格,示例如下:
grid = np.zeros(shape=(10000,10000), dtype=float) print(f'np.zeros(shape=(10000,10000), dtype=float) result: \n{grid}')
執行py文件,輸出結果如下:
np.zeros(shape=(10000,10000), dtype=float) result: [[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 print(f'grid + 10 result:\n{grid}') print(f'np.sin(grid) result:\n{np.sin(grid)}')
執行py文件,輸出結果如下:
grid + 10 result: [[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) result: [[-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列表的索引功能——特別是對于多維數組。為了演示多維數組的索引功能,首先構造一個簡單的二維數組:
a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]) print(f'a is:\n{a}') print(f'a[1] is:\n{a[1]}') print(f'a[:,1] is:\n{a[:,1]}') print(f'a[1:3, 1:3] is:\n{a[1:3, 1:3]}') a[1:3, 1:3] += 10 print(f'a is:\n{a}') print(f'a + [100, 101, 102, 103] is:\n{a + [100, 101, 102, 103]}') print(f'np.where(a < 10, a, 10) is:\n{np.where(a < 10, a, 10)}')
執行py文件,輸出結果如下:
a is: [[ 1 2 3 4] [ 5 6 7 8] [ 9 10 11 12]] a[1] is: [5 6 7 8] a[:,1] is: [ 2 6 10] a[1:3, 1:3] is: [[ 6 7] [10 11]] a is: [[ 1 2 3 4] [ 5 16 17 8] [ 9 20 21 12]] a + [100, 101, 102, 103] is: [[101 103 105 107] [105 117 119 111] [109 121 123 115]] np.where(a < 10, a, 10) is: [[ 1 2 3 4] [ 5 10 10 8] [ 9 10 10 10]]
NumPy是Python中很多科學與工程庫的基礎,同時也是被廣泛使用的最大、最復雜的模塊之一。NumPy通過一些簡單程序能完成有趣的事情。
通常,導入NumPy庫的時候,我們會使用語句import numpy as np。這樣就不用在程序中一遍遍地輸入numpy,只需要輸入np即可,節省了輸入時間。
- SQL Server 2012數據庫技術及應用(微課版·第5版)
- Swift 3 New Features
- Learning ELK Stack
- 快人一步:系統性能提高之道
- C++新經典
- Visual FoxPro程序設計習題集及實驗指導(第四版)
- Learning jQuery(Fourth Edition)
- App Inventor創意趣味編程進階
- JavaScript應用開發實踐指南
- Java EE企業級應用開發教程(Spring+Spring MVC+MyBatis)
- C++程序設計教程(第2版)
- 零基礎C#學習筆記
- SAP Web Dynpro for ABAP開發技術詳解:基礎應用
- R語言與網站分析
- jQuery Essentials