花式索引

阅读: 5579     评论:4

numpy提供了比常规的python序列更多的索引工具。正如我们前面看到的,除了按整数和切片索引之外,还可以使用数组进行索引

>>> a = np.arange(12)**2    
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])
>>>
>>> j = np.array( [ [ 3, 4], [ 9, 7 ] ] )     #一个二维索引数组
>>> a[j]                # 最终结果和j的形状保持一致
array([[ 9, 16],
       [81, 49]])

当被索引的数组是多维数组时,将按照它的第一轴进行索引的,比如下面的例子:

>>> 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]]])

我们这么理解:从image中每拿出一个元素,比如第一个元素0,然后去palette中找第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]])
>>> i = np.array( [ [0,1],                        
...                 [1,2] ] )
>>> j = np.array( [ [2,1],                        
...                 [3,3] ] )
>>>
>>> a[i,j]   
array([[ 2,  5],
       [ 7, 11]])
>>>
>>> a[i,2]
array([[ 2,  6],
       [ 6, 10]])
>>>
>>> a[:,j]                          
array([[[ 2,  1],
        [ 3,  3]],
       [[ 6,  5],
        [ 7,  7]],
       [[10,  9],
        [11, 11]]])

上面的例子,其实就是从i中拿一个数,再从j的相同位置拿一个数,组成一个索引坐标,再去a中找元素。这有个前提,就是i和j必须是同构的。

我们还可以这么做:

>>> k = [i,j]
>>> a[k]           # 等同于a[i,j]
array([[ 2,  5],
       [ 7, 11]])

但却不能这么做:

# 这个例子让人迷惑,所以不要自己给自己挖坑。简单的索引能达成目标,就不要玩花样。

>>> s = np.array( [i,j] )
>>> a[s]                            # 错误做法
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
IndexError: index (3) out of range (0<=index<=2) in dimension 0
>>>
>>> a[tuple(s)]           # 等同于a[i,j]
array([[ 2,  5],
       [ 7, 11]])

比较有用的是下面的技巧:

# 用一个列表作为索引参数

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

但是当索引出现重复的情况下,由最后的值决定最终结果:

>>> a = np.arange(5)
>>> a[[0,0,2]]=[1,2,3]
>>> a
array([2, 1, 3, 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”。


 广播机制 布尔索引 

评论总数: 4


点击登录后方可评论

在k = [i, j],然后输出a[k]的那一部分是否有误?因为当使用k=[i,j]时会报错,并且得不到文中给出的答案,但是将索引方式从列表换为元组时,即k = [i,j]换成k = (i,j)时,答案与文中符合,这两种索引方式应该是不同的。



多个索引参数那节注释有错 >>> a[i,j] # 等同于a[0][3],a[1][4]... 这里错了,应该是a[0][2],a[1][1],a[1][3],a[2][3]



感谢指出,已经修改。



多个或多维索引