Broadcasting允许通用函数以有意义的方式处理具有不完全相同形状的输入。
在应用广播规则之后,所有阵列的大小必须匹配。
(以上不是特别明白)
>>> a = np.arange(12)**2
>>> a
array([ 0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121],
dtype=int32)
>>> i = np.array([1,1,3,8,5])
>>> a[i]
array([ 1, 1, 9, 64, 25], dtype=int32)
>>>
>>> j = np.array([[3,4],[9,7]])
>>> a[j] # a[j] 形状与 j 一致
array([[ 9, 16],
[81, 49]], dtype=int32)
a
是一个多维数组,单个索引数组指的是 a
的第一个维度。以下示例通过使用调色板将标签图像转换为彩色图像来作为举例。>>> palette = np.array([[0,0,0],[255,0,0],[0,255,0],[0,0,255],[255,255,255]])
>>> image = np.array([[0,1,2,0],[0,3,4,0]])
>>> palette[image]
array([[[ 0, 0, 0],
[255, 0, 0],
[ 0, 255, 0],
[ 0, 0, 0]],
[[ 0, 0, 0],
[ 0, 0, 255],
[255, 255, 255],
[ 0, 0, 0]]])
>>> a = np.arange(12).reshape(3,4)
>>> a
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>> i = np.array([[0,1],[1,2]]) #行
>>> j = np.array([[2,1],[3,3]]) #列
>>> a[i,j] # i,j 必须有相同的shape
array([[ 2, 5],
[ 7, 11]])
>>>
>>> a[i,2]
array([[ 2, 6],
[ 6, 10]])
>>>
>>> a[:,j] #行和列的组合(0行所有的j...)
array([[[ 2, 1],
[ 3, 3]],
[[ 6, 5],
[ 7, 7]],
[[10, 9],
[11, 11]]])
i
和 j
放在一个序列中(比如一个列表), 然后用列表进行索引。>>> l = [i,j]
>>> a[l]
array([[ 2, 5], # 等效于 a[i,j]
[ 7, 11]])
i
和 j
放入一个数组中,因为这个数组将被解释为索引第一个维度。>>> s = np.array([i,j])
>>> s
array([[[0, 1],
[1, 2]],
[[2, 1],
[3, 3]]])
>>> a[s]
Traceback (most recent call last):
File "<pyshell#36>", line 1, in <module>
a[s]
IndexError: index 3 is out of bounds for axis 0 with size 3
>>> a[tuple(s)] # 与 a[i,j] 一样
array([[ 2, 5],
[ 7, 11]])
>>> time_max = time[idx]
>>> data_max = data[idx, range(data.shape[1])] # => data[idx[0],0], data[idx[1],1]...
>>> time_max
array([ 82.5 , 20. , 113.75, 51.25])
>>> data_max
array([0.98935825, 0.84147098, 0.99060736, 0.6569866 ])
>>> np.all(data_max == data.max(axis=0))
True
>>> a = np.arange(5)
>>> a
array([0, 1, 2, 3, 4])
>>> a[[1,2,3]] = 0
>>> a
array([0, 0, 0, 0, 4])
>>> a = np.arange(5)
>>> a[[0,0,2]] = [1,2,3] # a[0]=1,a[0]=2,a[2]=3
>>> a
array([2, 1, 3, 3, 4])
+=
构造要小心,可能得不到你想要的效果>>> a
array([0, 1, 2, 3, 4])
>>> a[[0,0,2]] += 1 # a[0] 只加了1次
>>> a
array([1, 1, 3, 3, 4])
即使0在索引列表中出现2次,第0个元素只会增加一次。这是因为Python要求“a + = 1”等同于“a = a + 1”
使用布尔值作为索引时,我们明确地选择数组中的哪些元素我们想要的,哪些不是。
我们可以想到的布尔索引最自然的方式是使用与原始数组具有相同形状的布尔数组
>>> a = np.arange(12).reshape(3,4)
>>> a
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>> b = a > 4
>>> b
array([[False, False, False, False],
[False, True, True, True],
[ True, True, True, True]])
>>> a[b] # 取出true的元素
array([ 5, 6, 7, 8, 9, 10, 11])
>>> a[b] = 0 # a中大于4的元素赋值为0
>>> a
array([[0, 1, 2, 3],
[4, 0, 0, 0],
[0, 0, 0, 0]])
使用布尔索引生成 Mandelbrot 集的图像(不懂)
import numpy as np
import matplotlib.pyplot as plt
def mandelbrot(h,w,maxit=20):
# Returns an image of the Mandelbrot fractal of size (h,w)
y,x = np.ogrid[-1.4:1.4:h*1j, -2:0.8:w*1j]
c = x+y*1j
z = c
divtime = maxit + np.zeros(z.shape, dtype=int)
for i in range(maxit):
z = z**2 + c
diverge = z*np.conj(z) > 2**2
div_now = diverge & (divtime==maxit)
divtime[div_now] = i
z[diverge] = 2
return divtime
plt.imshow(mandelbrot(400,400))
plt.show()
第二种使用布尔索引的方法更类似于整数索引; 对于数组的每个维度,给出一个一维布尔数组,选择我们想要的切片
>>> a = np.arange(12).reshape(3,4)
>>> b1 = np.array([False,True,True]) # 第一轴长度3=a中的3
>>> b2 = np.array([True,False,True,False]) # 第二轴长度4=a中的4
>>>
>>> a[b1,:] # 选择b1内true的行
array([[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>>
>>> a[b1] # 同上
array([[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>>
>>> a[:,b2] # 选择b2内true的列
array([[ 0, 2],
[ 4, 6],
[ 8, 10]])
>>>
>>> a[b1,b2] # 奇怪的结果!!!
array([ 4, 10])
1D布尔数组的长度必须与你要切片的维度(或轴)的长度一致。b1 是rank为1的数组,其长度为3( a 中行的数量), b2 (长度4)适合于索引 a 的第二个rank(列)。
可以使用 ix_ 函数来组合不同的向量以获得每个n-uplet的结果。例如,如果要计算从向量a、b和c中的取得的所有三元组的所有a + b * c
>>> a = np.array([2,3,4,5])
>>> b = np.array([8,5,4])
>>> c = np.array([5,4,6,8,3])
>>> ax,bx,cx = np.ix_(a,b,c) # 分别取对应的,组合
>>> ax
array([[[2]],
[[3]],
[[4]],
[[5]]])
>>> bx
array([[[8],
[5],
[4]]])
>>> cx
array([[[5, 4, 6, 8, 3]]])
>>> ax.shape, bx.shape, cx.shape
((4, 1, 1), (1, 3, 1), (1, 1, 5))
>>> result = ax+bx*cx
>>> result
array([[[42, 34, 50, 66, 26],
[27, 22, 32, 42, 17],
[22, 18, 26, 34, 14]],
[[43, 35, 51, 67, 27],
[28, 23, 33, 43, 18],
[23, 19, 27, 35, 15]],
[[44, 36, 52, 68, 28],
[29, 24, 34, 44, 19],
[24, 20, 28, 36, 16]],
[[45, 37, 53, 69, 29],
[30, 25, 35, 45, 20],
[25, 21, 29, 37, 17]]])
>>> result[3,2,4]
17
>>> a[3]+b[2]*c[4]
17
以下版本的reduce的优点是它使用Broadcasting规则,以避免创建参数数组输出的大小乘以向量的数量。
>>> def func(f, *vectors):
vs = np.ix_(*vectors)
r = f.identity
for v in vs:
r = f(r,v)
return r
>>> func(np.add,a,b,c)
array([[[15, 14, 16, 18, 13],
[12, 11, 13, 15, 10],
[11, 10, 12, 14, 9]],
[[16, 15, 17, 19, 14],
[13, 12, 14, 16, 11],
[12, 11, 13, 15, 10]],
[[17, 16, 18, 20, 15],
[14, 13, 15, 17, 12],
[13, 12, 14, 16, 11]],
[[18, 17, 19, 21, 16],
[15, 14, 16, 18, 13],
[14, 13, 15, 17, 12]]])
>>> a = np.array([[1.0,2.0],[3.0,4.0]])
>>> print(a)
[[1. 2.]
[3. 4.]]
>>> a.transpose() #转置
array([[1., 3.],
[2., 4.]])
>>> np.linalg.inv(a) #矩阵求逆
array([[-2. , 1. ],
[ 1.5, -0.5]])
>>> u = np.eye(2) #对角线是1
>>> u
array([[1., 0.],
[0., 1.]])
>>> j = np.array([[0.0,-1.0],[1.0,0.0]])
>>> np.dot(j,j) #矩阵点积
array([[-1., 0.],
[ 0., -1.]])
>>> np.trace(u)
2.0
>>> y = np.array([[5.0],[7.0]])
>>> np.linalg.solve(a,y) # 求解矩阵方程
array([[-3.],
[ 4.]])
>>> np.linalg.eig(j)
(array([0.+1.j, 0.-1.j]), array([[0.70710678+0.j , 0.70710678-0.j ],
[0. -0.70710678j, 0. +0.70710678j]]))
可以省略一个维度的尺寸,由其自动计算出来
>>> a = np.arange(30)
>>> a.shape = 2,-1,3 # -1 表示自行推导,省略
>>> a.shape
(2, 5, 3)
>>> a
array([[[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11],
[12, 13, 14]],
[[15, 16, 17],
[18, 19, 20],
[21, 22, 23],
[24, 25, 26],
[27, 28, 29]]])
column_stack,dstack,hstack,vstack
>>> x = np.arange(0,10,2) #array([0, 2, 4, 6, 8])
>>> y = np.arange(5) #array([0, 1, 2, 3, 4])
>>> m = np.vstack([x,y])
>>> m
array([[0, 2, 4, 6, 8],
[0, 1, 2, 3, 4]])
>>> xy = np.hstack([x,y])
>>> xy
array([0, 2, 4, 6, 8, 0, 1, 2, 3, 4])