矢量化計算
概念是:用數組表達式代替循環。
例:計算點(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。