lee-romantic 's Blog
Everything is OK!
Toggle navigation
lee-romantic 's Blog
主页
About Me
归档
标签
numpy中数组索引(包括高级用法)
2019-04-03 16:17:06
1354
0
0
lee-romantic
最近在研究一个仿射变换的代码时,发现下面没见过的的`numpy`数组索引方法: ``` #shape of input_img :(2,187,300,3) #shape of y0 and x0:(2,187,300) #shape of Ia:(2,187,300,3) Ia = input_img[np.arange(num_batch)[:,None,None], y0, x0] ``` 这是在用`numpy`数组索引数组。先回顾下基础: ###**一、单个元素索引** 一维数组索引 ``` >>> x = np.arange(10) >>> x[2] 2 >>> x[-2] 8 ``` 二维数组索引 ``` >>> x.shape = (2,5) # now x is 2-dimensional >>> x[1,3] 8 >>> x[1,-1] 9 ``` 数组切片 ``` >>> x = np.arange(10) >>> x[2:5] array([2, 3, 4]) >>> x[:-7] array([0, 1, 2]) >>> x[1:7:2] array([1, 3, 5]) >>> y = np.arange(35).reshape(5,7) >>> y[1:5:2,::3] array([[ 7, 10, 13], [21, 24, 27]]) ``` ###**二、使用数组索引数组** 例:产生一个一组数组,使用数组来索引出需要的元素。让数组[3,3,1,8]取出x中的第3,3,1,8的四个元素组成一个数组view ``` >>> x = np.arange(10,1,-1) >>> x array([10, 9, 8, 7, 6, 5, 4, 3, 2]) >>> x[np.array([3, 3, 1, 8])] array([7, 7, 9, 2]) ``` 当然,类似切片那样,Index也可以使用负数。但是索引值不能越界! ``` >>> x[np.array([3,3,-3,8])] array([7, 7, 4, 2]) ``` ###**三、索引多维数组** 例1:产生一个5X7的数组,选择0,2,4行,0,1,2列的数 ``` >>> y = np.arange(35).reshape(5,7) >>> y[np.array([0,2,4]), np.array([0,1,2])] array([ 0, 15, 30]) ``` 例2:选取第0,2,4行,第1列的值 ``` >>> y[np.array([0,2,4]), 1] array([ 1, 15, 29]) ``` 例3:选取第0,2,4行的值 ``` >>> y[np.array([0,2,4])] array([[ 0, 1, 2, 3, 4, 5, 6], [14, 15, 16, 17, 18, 19, 20], [28, 29, 30, 31, 32, 33, 34]]) ``` ###**四、布尔值或掩码索引数组** 例1 ``` >>> y = np.arange(35) >>> b = y>20 >>> y[b] array([21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34]) ``` 例2 ``` >>> b[:,5] # use a 1-D boolean whose first dim agrees with the first dim of y array([False, False, False, True, True], dtype=bool) >>> y[b[:,5]] array([[21, 22, 23, 24, 25, 26, 27], [28, 29, 30, 31, 32, 33, 34]]) ``` 例3 ``` >>> x = np.arange(30).reshape(2,3,5) >>> x 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]]]) >>> b = np.array([[True, True, False], [False, True, True]]) >>> x[b] array([[ 0, 1, 2, 3, 4], [ 5, 6, 7, 8, 9], [20, 21, 22, 23, 24], [25, 26, 27, 28, 29]]) ``` ###**五、数组与切片的组合索引数组** 例1:产生一个5X7的数组,使用数组来索引第一个轴,使用切换来索引第二个轴 ``` >>> y = np.arange(35).reshape(5,7) >>> y[np.array([0,2,4]),1:3] array([[ 1, 2], [15, 16], [29, 30]]) ``` 例2:切片与布尔类型索引 ``` >>> y[b[:,5],1:3] array([[22, 23], [29, 30]]) ``` ###**六、Structural indexing tools** 例1:使用np.newwaxis可以直接扩展维度 ``` >>> y.shape (5, 7) >>> y[:,np.newaxis,:].shape (5, 1, 7) ``` 例2:这是利用了扩展维度与广播特性的矩阵相加。用5X1矩阵与1X5矩阵相加。 ``` >>> x = np.arange(5) >>> x[:,np.newaxis] + x[np.newaxis,:] array([[0, 1, 2, 3, 4], [1, 2, 3, 4, 5], [2, 3, 4, 5, 6], [3, 4, 5, 6, 7], [4, 5, 6, 7, 8]]) ``` 例3:使用 ... 符号来表示其他维度 ``` >>> z = np.arange(81).reshape(3,3,3,3) >>> z[1,...,2] array([[29, 32, 35], [38, 41, 44], [47, 50, 53]]) ``` 这例子也相当于下面的代码实现 ``` >>> z[1,:,:,2] array([[29, 32, 35], [38, 41, 44], [47, 50, 53]]) ``` 参考:https://www.cnblogs.com/McKean/p/6412164.html ###**七.高级用法** 1. 使用索引数组进行索引 ``` >>> a = np.arange(12)**2 # the first 12 square numbers >>> i = np.array( [ 1,1,3,8,5 ] ) # an array of indices >>> a[i] # the elements of a at the positions i array([ 1, 1, 9, 64, 25]) >>> >>> j = np.array( [ [ 3, 4], [ 9, 7 ] ] ) # a bidimensional array of indices >>> a[j] # 生成的数组形状和j一样 array([[ 9, 16], [81, 49]]) ``` 如果被索引的数组a是多维的,那么索引数组将引用数组a的第一维(当然,这是对于只有`一个索引数组`而言的,如果有多个索引数组的话,则可以索引更底层的数据)。 ``` >>> palette = np.array( [ [0,0,0], # black ... [255,0,0], # red ... [0,255,0], # green ... [0,0,255], # blue ... [255,255,255] ] ) # white >>> image = np.array( [ [ 0, 1, 2, 0 ], # each value corresponds to a color in the palette ... [ 0, 3, 4, 0 ] ] ) >>> palette[image] # the (2,4,3) color 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]]]) ``` 也可以给出多于1维的索引。`针对每个维的索引数组必须形状相同`。 ``` >>> 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形状必须相同 array([[ 2, 5], [ 7, 11]]) ``` 解释一下这个过程: `a[i,j]`的机制是`数组i和数组j相同位置的对应数字两两组成一对索引`,然后用这对索引在数组a中进行取值。比如数组i的索引(0,0)处的值为0,数组j的索引(0,0)处的值为2,它们组成的索引对是(0,2),在数组a中对应的值是2。在这样的机制下,理所当然要求数组i和数组j需要有相同的形状,否则将无法取得相应的索引对。又因为数组i和数组j分别是数组a的两个轴(axis)上的索引数组,所以最终的结果也就和数组i/j的形状相同。 ``` >>> a[i,2] array([[ 2, 6], [ 6, 10]]) ``` 上面的过程是:数组i是数组a第一个轴的索引数组,a[i,2]中的数字2表示数组a的第二个轴的索引,数组i中的每个数字都与2组成索引对,也就是([ [(0,2), (1,2)], [(1,2),(2,2)] ]),然后依据这些索引对和相应的形状取数组a中的值。 ``` >>> a[:,j] array([[[ 2, 1], [ 3, 3]], [[ 6, 5], [ 7, 7]], [[10, 9], [11, 11]]]) ``` 上面的过程是:对数组a第一个轴进行完整切片,得到(0,1,2),然后每个值都与数组j中的元素两两组成索引对,也就是组成3个二维索引对,然后根据索引对取数组a中的值。 自然,我们也可以将i和j放入一个序列(比如一个列表)中,然后用这个序列进行索引。 ``` >>> l = [i,j] >>> a[l] # 等价于 a[i,j] array([[ 2, 5], [ 7, 11]]) ``` 但是,`我们不能把i和j组成大数组后再去对数组a进行索引`,因为根据前面的内容,我们知道,用1个索引数组对另一个数据索引时,索引数组中的元素都被解释成数组a第一维的索引。 更多详细介绍,参考链接: https://blog.csdn.net/wangwenzhi276/article/details/53436694 ###**八.回顾** 回顾开头的问题, ``` #shape of input_img :(2,187,300,3) #shape of y0 and x0:(2,187,300) #shape of Ia:(2,187,300,3) Ia = input_img[np.arange(num_batch)[:,None,None], y0, x0] ``` 从高级用法中可以知道,使用多维数组索引多维数组,那么作为索引的数组必须具有相同的形状,或者可以通过广播匹配为相同的形状,但是,`np.arange`形状与`y0,x0`均不一样,且无法广播匹配(广播只能在形状最前面的维度增加1),因此通过`None`,在后面增加一的维度,从而与`y0,x0`可以广播匹配, 而至于`input_img`的最后一个维度3,索引时作为一个整体即可,因此最后输出的维度,为`x0,y0`的形状,加上维度3的形状,输出为`shape of Ia:(2,187,300,3)`
上一篇:
C++中NULL和nullptr
下一篇:
python3二维字典更新的问题
0
赞
1354 人读过
新浪微博
微信
腾讯微博
QQ空间
人人网
提交评论
立即登录
, 发表评论.
没有帐号?
立即注册
0
条评论
More...
文档导航
没有帐号? 立即注册