矢量化计算
概念是:用数组表达式代替循环。
例:计算点(x,y)到原点的长度。首先介绍一个函数,np.meshgrid(*x,*y)。这个函数接收两个数组*x,*y,对于这两个数组上的所有元素,进行一一对应,生成两个矩阵,两个矩阵相同位置上的元素就是点的x和y坐标。
points = np.arange(-5,5,0.01,dtype=np.float64)
xs,ys = np.meshgrid(points,points)
xs
'''
结果:
array([[-5. , -4.99, -4.98, ..., 4.97, 4.98, 4.99],
[-5. , -4.99, -4.98, ..., 4.97, 4.98, 4.99],
[-5. , -4.99, -4.98, ..., 4.97, 4.98, 4.99],
...,
[-5. , -4.99, -4.98, ..., 4.97, 4.98, 4.99],
[-5. , -4.99, -4.98, ..., 4.97, 4.98, 4.99],
[-5. , -4.99, -4.98, ..., 4.97, 4.98, 4.99]])
ys是xs的转置
'''
下面就是调用np.sqrt对数组进行处理:
z = np.sqrt(xs ** 2+ys ** 2)
print(z)
'''
结果:
[[7.07106781 7.06400028 7.05693985 ... 7.04988652 7.05693985 7.06400028]
[7.06400028 7.05692568 7.04985815 ... 7.04279774 7.04985815 7.05692568]
[7.05693985 7.04985815 7.04278354 ... 7.03571603 7.04278354 7.04985815]
...
[7.04988652 7.04279774 7.03571603 ... 7.0286414 7.03571603 7.04279774]
[7.05693985 7.04985815 7.04278354 ... 7.03571603 7.04278354 7.04985815]
[7.06400028 7.05692568 7.04985815 ... 7.04279774 7.04985815 7.05692568]]
'''
尝试将其可视化,提前感受一下(虽然这个函数我看不懂):
将条件逻辑表述为数组运算
np.where(condition,x,y)(注意顺序)函数是x if condition else y表达式的矢量化(数组版),但它的参数可以不是数组。
例:首先有这样三个数组:
x = np.array([1.1,1.2,1.3,1.4,1.5])
y = np.array([2.1,2.2,2.3,2.4,2.5])
cond = np.array([True,False,True,True,False])
若想要实现cond为True时从x选取,cond为False时从y选取,传统Python解决方式为:
result = [(x if z else y)
for x,y,z in zip(x,y,cond)]
result
#结果:[1.1, 2.2, 1.3, 1.4, 2.5]
看着是没什么毛病,但是很显然,当数组很大时,for循环占用空间大的缺点就暴露出来了。若用np.where,不仅能处理大叔组,写起来也很简洁:
result_wh = np.where(cond,x,y)
result_wh
#结果:[1.1, 2.2, 1.3, 1.4, 2.5]
np.where函数能够处理更复杂的逻辑问题,将来若有需要希望别忘了它。
数学统计方法
arr = np.random.randn(5,4)
#求算数平均数
arr.mean()
#结果:-0.10653246371327466
#求所有元素之和
arr.sum()
#结果:-2.0196217215714967
这两种方法接收一个axis参数,这样计算的就是该轴上的统计值:
#求某轴向的所有元素的和
arr.sum(axis=0)
#array([-0.75673429, 1.70129588, -0.95407974, -4.86702506])
arr.sum(1)
#array([-0.58449652, -0.50289763, -0.21146403, -3.79389472, 0.21620969])
还有一些其他方法:
std:求标准差 var:求方差
min,max:求最小值和最大值
argmin,argmax:求最小值和最大值的索引
cumsum:所有元素的累计和(每一维或每个数累积一次)
cumprod:所有元素的累计积
arr = np.array([[1,2,3],[4,5,6],[7,8,9]])
print(arr.cumsum())
#[ 1 3 6 10 15 21 28 36 45]
print(arr.cumsum(0))
'''
[[ 1 2 3]
[ 5 7 9]
[12 15 18]]
'''
排序
数组排序运用的也是sort就地排序(即会改动数组),同样,sort也支持在一个轴向上排序。
arr = np.random.randn(5,3)
print(arr)
print('*'*40)
arr.sort(1)
print(arr)
'''
结果:
[[ 2.16177016 0.08249236 -0.2261361 ]
[-0.55112602 -1.6953063 0.77323005]
[-0.21736826 -0.26397035 1.20148955]
[-1.97900358 -0.90121201 0.21595791]
[ 1.28279156 0.69281414 2.59958602]]
****************************************
[[-0.2261361 0.08249236 2.16177016]
[-1.6953063 -0.55112602 0.77323005]
[-0.26397035 -0.21736826 1.20148955]
[-1.97900358 -0.90121201 0.21595791]
[ 0.69281414 1.28279156 2.59958602]]
'''
其他集合逻辑
*注意!这些函数仅仅用于一维数组!
np.unique():计算x中的唯一元素(即去掉重复值),并返回有序结果。
a = np.array([34,235,54,23,43,23,4,5,235,5])
np.unique(a)
#结果:array([ 4, 5, 23, 34, 43, 54, 235])
np.in1d(*x,*y):测试数组x在数组y中的成员资格。
intersect1d(*x,*y):计算x,y的公共元素,并返回有序结果。
union1d(*x,*y):计算x,y的并集,并返回有序结果。
in1d(*x,*y):得到一个表示“x的元素是否包含于y”的bool型数组。
setdiff1d(*x,*y):集合的差,x-y。