官术网_书友最值得收藏!

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即可,節省了輸入時間。

主站蜘蛛池模板: 枝江市| 青龙| 新源县| 即墨市| 腾冲县| 兴城市| 连州市| 正定县| 祁连县| 岳普湖县| 乌鲁木齐市| 九龙城区| 肃北| 桦南县| 四子王旗| 图们市| 和平区| 新野县| 威海市| 盘山县| 余姚市| 马关县| 新密市| 宁河县| 新余市| 宜春市| 大埔县| 琼结县| 崇信县| 景洪市| 兴化市| 清原| 云和县| 体育| 巩留县| 通江县| 龙江县| 合阳县| 淮滨县| 临澧县| 虹口区|