Numpy进阶之Less基础

花式索引和索引技巧:

>>> 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,5,8])
>>> a[i]
array([ 1,  1,  9, 25, 64], dtype=int32)
>>> j = np.array([[3,4],[9,7]])
>>> a[j]
array([[ 9, 16],
       [81, 49]], dtype=int32)
>>> a[[j]]
array([[ 9, 16],
       [81, 49]], dtype=int32)
>>> a[np.array([i,i])]
array([[ 1,  1,  9, 25, 64],
       [ 1,  1,  9, 25, 64]], dtype=int32)
>>>

我们也可以给出多个维度的索引。每个维度的索引数组必须具有相同的形状。

>>> a = np.arange(12)
>>> a.shape=3,4
>>> a
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
>>> i = np.array([[0,1]])
>>>> i = np.array([[0,1],[1,2]])
>>> j = np.array([[2,1],[3,3]])
>>> a[i,j]
array([[ 2,  5],
       [ 7, 11]])
>>> a[i,j]
array([[ 2,  5],
       [ 7, 11]])
>>> l = [i,j]
>>> a[l]
array([[ 2,  5],
       [ 7, 11]])
>>> a[:,j]
array([[[ 2,  1],
        [ 3,  3]],

       [[ 6,  5],
        [ 7,  7]],

       [[10,  9],
        [11, 11]]])
>>> 

最后那种情况是对每一行进行索引。
我们不能将 i 和 j 放入一个数组中,因为这个数组将被解释为索引第一个维度。

>>> s = np.array([i,j])
>>> a[s]
Traceback (most recent call last):
  File "<pyshell#174>", line 1, in <module>
    a[s]
IndexError: index 3 is out of bounds for axis 0 with size 3
>>> a.size
12
>>> a.shape
(3, 4)
>>> a
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
>>> a[tuple(s)]
array([[ 2,  5],
       [ 7, 11]])
>>> s
array([[[0, 1],
        [1, 2]],

       [[2, 1],
        [3, 3]]])
>>> 

索引数组的另一个常见用途是搜索时间相关序列的最大值:

>>> time = np.linspace(20,145,5)
>>> time
array([ 20.  ,  51.25,  82.5 , 113.75, 145.  ])
>>> data = np.sin(np.arange(20)).reshape(5,4)
>>> data
array([[ 0.        ,  0.84147098,  0.90929743,  0.14112001],
       [-0.7568025 , -0.95892427, -0.2794155 ,  0.6569866 ],
       [ 0.98935825,  0.41211849, -0.54402111, -0.99999021],
       [-0.53657292,  0.42016704,  0.99060736,  0.65028784],
       [-0.28790332, -0.96139749, -0.75098725,  0.14987721]])
>>> ind = data.argmax(axis=0)
>>> ind
array([2, 0, 3, 1], dtype=int64)
>>> time_max = time[ind]
>>> time_max
array([ 82.5 ,  20.  , 113.75,  51.25])
>>> data_max = data[ind,range(data.shape[1])]
>>> 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,3,4]]=-1
		  
>>> a
		  
array([ 0, -1,  2, -1, -1])
>>> 

然而,当索引列表包含重复时,赋值完成多次,留下最后一个值:

>>> a = np.arange(5)
		  
>>> a[[1,1,1]] = [-1,-2,-3]
		  
>>> a
		  
array([ 0, -3,  2,  3,  4])

如果你想使用Python的 += 构造要小心,因为这可能得不到你想要的效果:

>>> a = np.arange(5)
		  
>>> a[[0,0,2]] += 1
		  
>>> a
		  
array([1, 1, 3, 3, 4])

即使0在索引列表中出现两次,第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]
		  
array([ 5,  6,  7,  8,  9, 10, 11])
>>> 

注意返回的是一维数组。

这种方法常用于赋值:

>>> a[b] = 0
		  
>>> a
		  
array([[0, 1, 2, 3],
       [4, 0, 0, 0],
       [0, 0, 0, 0]])
>>> 

第二种使用布尔索引的方法更类似于整数索引;对于数组的每个维度,我们给出一个一维布尔数组,选择我们想要的切片:

>>> a = np.arange(12).reshape(3,4)
>>> a
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
>>> b1 = np.array([False,True,True])
>>> b2 = np.array([True,False,True,False])
>>> a[b1,:]
array([[ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
>>> a[:,b2]
array([[ 0,  2],
       [ 4,  6],
       [ 8, 10]])
>>> a[b1,b2]
array([ 4, 10])
>>> 

请注意,1D布尔数组的长度必须与你要切片的维度(或轴)的长度一致。在前面的示例中, b1 是rank为1的数组,其长度为3( a 中行的数量), b2 (长度4)适合于索引 a 的第二个rank(列)。

ix_()函数:

>>> 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.shape
(4, 3, 5)
>>> bx * cx
array([[[40, 32, 48, 64, 24],
        [25, 20, 30, 40, 15],
        [20, 16, 24, 32, 12]]])
>>> (bx * cx).shape
(1, 3, 5)
>>> 

这里用到了广播,所以可能有点不好理解。

还有另一种实现方式:

>>> def ufunc_reduce(ufct,*vec):
	vs = np.ix_(*vec)
	r = ufct.identity
	print("first r:",r)
	for v in vs:
		r = ufct(r,v)
		print("r:",r)
	return r

>>> ufunc_reduce(np.add,a,b,c)
first r: 0
r: [[[2]]

 [[3]]

 [[4]]

 [[5]]]
r: [[[10]
  [ 7]
  [ 6]]

 [[11]
  [ 8]
  [ 7]]

 [[12]
  [ 9]
  [ 8]]

 [[13]
  [10]
  [ 9]]]
r: [[[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]]]
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]]])
>>> 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值