问题:
你需要在数据集(比如数组或网格)上面执行计算:
解决方案:
涉及到数组的重量级运算操作,可以使用NumPy库。NumPy的一个主要特征是它会给Python提供一个数组对象,相比标准的Python列表已更适合用来做数学运算。下面是一个简单的小例子,向你展示标准列表对象和NumPy数组之间的差别:
x = [1, 2, 3, 4]
y = [5, 6, 7, 8]
print(x * 2) #->[1, 2, 3, 4, 1, 2, 3, 4]
# print(x + 10)
print(x+y) # ->[1, 2, 3, 4, 5, 6, 7, 8]
import numpy as np
ax=np.array([1,2,3,4])
ay=np.array([5,6,7,8])
print(ax*2) # ->[2 4 6 8]
print(ax+10) #->[11 12 13 14]
print(ax+ay)# ->[ 6 8 10 12]
print(ax*ay)# ->[ 5 12 21 32]
正如所见,两种方案中数组的基本数学运算结果并不相同。特别的,Numpy中的标量运算(比如ax*2或ax+10)会作用在每个元素上。另外,当两个操作数都是数组的时候执行元素对等位置计算,并最终生成一个新的数组。
对整个数组中所有元素同时执行数学运算可以使得作用在整个数组上的函数运算简单而又快速。比如,如果你想计算多项式的值,可以这样做:
def f(x):
return 3*x**2 -2*x+7
print(f(ax)) #->[ 8 15 28 47]
Numpy还为数组操作提供了大量的通用函数,这些函数可以作为math模块中类似函数的替代。比如:
print(np.sqrt(ax)) #->[1. 1.41421356 1.73205081 2. ]
print(np.cos(ax))#->[ 0.54030231 -0.41614684 -0.9899925 -0.65364362]
使用这些通用函数要比循环数组并使用math模块中的函数执行计算要快的多。因此,只要可能额话尽量多选则numpy的数组方案。
底层实现中,Numpy数组使用功能了C或Fortan语言的机制分配内存。也就是说,它们是一个非常大的连续的并由同类型数组组成的内存区域。所以,你可以构造一个比普通pyhton列表大的多的数组。比如,如果你想构造一个1000*10000的浮点数二维网格,很轻松。
print(np.zeros(shape=(10000,10000),dtype=float))
'''
[[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=np.zeros(shape=(10000,10000),dtype=float)
print(grid)
'''
[[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(grid)
'''
[[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.]]
'''
print(np.sin(grid))
'''
[[-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(a)
'''
[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]]
'''
print(a[1])
print(a[:,1])
'''
[5 6 7 8]
[ 2 6 10]
'''
print(a[1:3,1:3])
'''
[[ 6 7]
[10 11]]
'''
a[1:3,1:3]+=10
print(a)
'''
[[ 1 2 3 4]
[ 5 16 17 8]
[ 9 20 21 12]]
'''
print(a+[100,101,102,103])
'''
[[101 103 105 107]
[105 117 119 111]
[109 121 123 115]]
'''
print(a)
'''
[[ 1 2 3 4]
[ 5 16 17 8]
[ 9 20 21 12]]
'''
print(np.where(a<10,a,10))
'''
[[ 1 2 3 4]
[ 5 10 10 8]
[ 9 10 10 10]]
'''