Python科学计算(第2版)
上QQ阅读APP看书,第一时间看更新

2.3.4 布尔数组作为下标

当使用布尔数组直接作为下标对象或者元组下标对象中有布尔数组时,都相当于用nonzero()将布尔数组转换成一组整数数组,然后使用整数数组进行下标运算。

nonzero(a)返回数组a中值不为零的元素的下标,它的返回值是一个长度为a.ndim(数组a的轴数)的元组,元组的每个元素都是一个整数数组,其值为非零元素的下标在对应轴上的值。例如对于一维布尔数组b1,nonzero(a)所得到的是一个长度为1的元组,它表示b1[0]和b1[2]的值不为0。

若只需要沿着指定轴通过布尔数组获取元素,可以使用numpy.compress()函数。

    b1 = np.array([True, False, True, False])
    np.nonzero(b1)
    (array([0, 2]),)

对于二维数组b2,nonzero(a)所得到的是一个长度为2的元组。它的第0个元素是数组a中值不为0的元素的第0轴的下标,第1个元素则是第1轴的下标,因此从下面的结果可知b2[0,0]、b2[0,2]和b2[1,0]的值不为0:

    b2 = np.array([[True, False, True], [True, False, False]])
    np.nonzero(b2)
    (array([0, 0, 1]), array([0, 2, 0]))

当布尔数组直接作为下标时,相当于使用由nonzero()转换之后的元组作为下标对象:

    a = np.arange(3 * 4 * 5).reshape(3, 4, 5)
            a[b2]             a[np.nonzero(b2)]   
    ----------------------  ----------------------
    [[ 0,  1,  2,  3,  4],[[ 0,  1,  2,  3,  4],
     [10, 11, 12, 13, 14],[10, 11, 12, 13, 14],
     [20, 21, 22, 23, 24]][20, 21, 22, 23, 24]]

当下标对象是元组,并且其中有布尔数组时,相当于将布尔数组展开为由nonzeros()转换之后的各个整数数组:

      a[1:3, b2]    a[1:3, np.nonzero(b2)[0], np.nonzero(b2)[1]]
    --------------  --------------------------------------------
    [[20, 22, 25],  [[20, 22, 25],                              
     [40, 42, 45]]   [40, 42, 45]]