我是靠谱客的博主 欣慰哈密瓜,这篇文章主要介绍Numpy进阶之Less基础,现在分享给大家,希望可以做个参考。

花式索引和索引技巧:

复制代码
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
30
31
32
33
34
35
>>> 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) >>>

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

复制代码
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
>>> 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 放入一个数组中,因为这个数组将被解释为索引第一个维度。

复制代码
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
30
31
32
>>> 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]]]) >>>

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

复制代码
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
30
31
32
33
34
35
36
37
38
39
40
>>> 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 >>>

可以使用数组索引作为目标来赋值:

复制代码
1
2
3
4
5
6
7
8
9
>>> a = np.arange(5) >>> a array([0, 1, 2, 3, 4]) >>> a[[1,3,4]]=-1 >>> a array([ 0, -1, 2, -1, -1]) >>>

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

复制代码
1
2
3
4
5
6
7
8
>>> a = np.arange(5) >>> a[[1,1,1]] = [-1,-2,-3] >>> a array([ 0, -3, 2, 3, 4])

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

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

即使0在索引列表中出现两次,第0个元素只会增加一次。这是因为Python要求“a + = 1”等同于“a = a + 1”。

使用布尔值作为数组索引:
布尔索引最自然的方式是使用与原始数组具有相同形状的布尔数组:

复制代码
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
30
31
>>> 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]) >>>

注意返回的是一维数组。

这种方法常用于赋值:

复制代码
1
2
3
4
5
6
7
>>> a[b] = 0 >>> a array([[0, 1, 2, 3], [4, 0, 0, 0], [0, 0, 0, 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
30
31
>>> 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_()函数:

复制代码
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
30
31
32
33
34
35
36
37
38
39
40
41
>>> 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) >>>

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

还有另一种实现方式:

复制代码
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
>>> 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]]]) >>>

最后

以上就是欣慰哈密瓜最近收集整理的关于Numpy进阶之Less基础的全部内容,更多相关Numpy进阶之Less基础内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(146)

评论列表共有 0 条评论

立即
投稿
返回
顶部