zoukankan      html  css  js  c++  java
  • numpy 索引

    一、花式索引

    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必须是同构的。

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

    # 用一个列表作为索引参数
    
    >>> 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”。

    二、布尔索引

    numpy给我们带来的最神奇的操作其实是布尔数组索引方法。

    使用布尔数组进行索引,其实就是我们显式地选择数组中需要哪些项,不需要哪些项。

    最自然的方法是使用与原始数组形状相同的布尔数组进行筛选过滤:

    >>> a = np.arange(12).reshape(3,4)
    >>> b = a > 4
    >>> b   # 通过比较运算,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]])

    实际上,上面的操作可以简写成:a[a>4] = 0

    使用~可以对布尔值取反,|表示或,&表示与:

    >>> a[~b]
    array([0, 1, 2, 3, 4])
    >>> (a<4)|(a>7)
    array([[ True,  True,  True,  True],
           [False, False, False, False],
           [ True,  True,  True,  True]])
    >>> a[(a<4)|(a>7)]
    array([ 0,  1,  2,  3,  8,  9, 10, 11])
    >>> (a>3)&(a<8)
    array([4, 5, 6, 7])

    下面是一个例子:

    >>> a = np.arange(12).reshape(3,4)
    >>> b1 = np.array([True,False,True])
    
    >>> b1.nonzero()   # 调用nonzero方法,就相当于将值为True的下标索引拿出来,保存到一个新数组中
    (array([0, 2], dtype=int64),)
    
    >>> a[b1]
    array([[ 0,  1,  2,  3],
           [ 8,  9, 10, 11]])
    
    >>> a[b1.nonzero()]             #可以看到,布尔数组索引等同于它的nonzero()数组索引的结果
    array([[ 0,  1,  2,  3],
           [ 8,  9, 10, 11]])
    
    >>> b2 = np.array([True,False,True,False])
    
    >>> b2.nonzero()
    (array([0, 2], dtype=int64),)
    
    >>> a[b2.nonzero()]
    array([[ 0,  1,  2,  3],
           [ 8,  9, 10, 11]])
    
    >>> a[b1,b2]    
    array([ 0, 10])
    
    >>> a[b1.nonzero(), b2.nonzero()]       # 同时使用两个布尔数组进行索引, 相当于用它们的nonzero()进行索引
    array([[ 0, 10]])       # 也就是获取a[0][0],a[2][2]。理解这点很重要!这时候从按行列索引,变成了按下标组合的索引方式。
    
    
    
    # 要注意的是使用这种方法,b1和b2布尔数组的长度,必须相等或者可以广播。注意,这个广播机制很重要!
    >>> b2 = np.array([True,False,True,True])
    
    >>> b2.nonzero()
    (array([0, 2, 3], dtype=int64),)
    
    >>> a[b1, b2]
    IndexError                                Traceback (most recent call last)
    <ipython-input-26-c7d1e0872c96> in <module>
    ----> 1 a[b1, b2]
    
    IndexError: shape mismatch: indexing arrays could not be broadcast together with shapes (2,) (3,) 
    #上面,长度2和长度3的两个索引数组无法广播,所以会出错。而下面长度1和2的两个数组,长度为1的可以广播,因此不会报错。
    
    
    >>> b2 = np.array([False,False,True,False])
    
    >>> b2.nonzero()
    (array([2], dtype=int64),)
    >>> a[b1,b2]
    array([ 2, 10])
  • 相关阅读:
    MySQL--字符集参数
    MySQL--字符集基础
    Cassandra基础2
    Cassandra基础
    Cassandra -- Cassandra 3.0版本安装
    Cassandra Demo--Python操作cassandra
    MySQL--批量插入导致自增跳号问题
    MySQL Disk--SSD和HDD的性能
    MySQL Lock--并发插入导致的死锁
    TCL-视图
  • 原文地址:https://www.cnblogs.com/lavender1221/p/12651442.html
Copyright © 2011-2022 走看看