【numpy】numpy中np.nonzero()的用法

nonzero(a) 返回数组a中非零元素的索引值数组。

  1. 只有a中非零元素才会有索引值,那些零值元素没有索引值;
  2. 返回的索引值数组是一个2维tuple数组,该tuple数组中包含一维的array数组。其中,一维array向量的个数与a的维数是一致的。
  3. 索引值数组的每一个array均是从一个维度上来描述其索引值。比如,如果a是一个二维数组,则索引值数组有两个array,第一个array从行维度来描述索引值;第二个array从列维度来描述索引值。
  4. 该np.transpose(np.nonzero(x))函数能够描述出每一个非零元素在不同维度的索引值。
  5. 通过a[nonzero(a)]得到所有a中的非零值

特别地,归于最后生成元组里数据的长度,有多少的非零元素,就有多长! 

nonzeros(a)返回数组a中值不为零的元素的下标,它的返回值是一个长度为a.ndim(数组a的轴数)的元组,元组的每个元素都是一个整数数组,其值为非零元素的下标在对应轴上的值。

b0 =np.array([1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1])
# 可以看出是第0,13,17的位置上元素非0,也就是说 nunzero函数是找出矩阵中非零元素的位置
print(np.nonzero(b0)) # (array([ 0, 13, 17], dtype=int64),)
# 这样一般使用
value_pos = np.nonzero(b0)[0]
print(value_pos) # [ 0 13 17]

例如对于一维布尔数组b1,nonzero(b1)所得到的是一个长度为1的元组,它表示b1[0]和b1[2]的值不为0(False)。  


b1 = np.array([True, False, True, False])
# 计算的是:值不为零(False)的元素的下标,这里index=0和index=2是不为0的
print(np.nonzero(b1))  # (array([0, 2], dtype=int64),)

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

b2 = np.array([[True, False, True], [True, False, False]])
# nonzero(b2)所得到的是一个长度为2的元组
print(np.nonzero(b2)) 
# (array([0, 0, 1], dtype=int64), array([0, 2, 0], dtype=int64))

解释如下,它是每一维,每一维单独统计(可能描述不太准确)。

如下图,矩阵中不为0(FALSE)的位置是篮圈,统计每个篮圈的数据。

首先是黄色的点,第一个T的黄点是0,第二个T的黄点是0,第三个T的黄点是1,所以元祖的第一个数据是(0,0,1);

其次是绿色的点,第一个T的绿点是0,第二个T的绿点是2,第三个T的绿点是0,所以元祖的第二个数据是(0,2,0)。

不是布尔类型时,直接看例子。核心思想还是找到非0元素的位置

b3 = np.arange(3*4*5).reshape(3,4,5)
print(b3)
"""
[[[ 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 32 33 34]
  [35 36 37 38 39]]

 [[40 41 42 43 44]
  [45 46 47 48 49]
  [50 51 52 53 54]
  [55 56 57 58 59]]]
"""
print(np.nonzero(b3))
"""
(array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2], dtype=int64), 
array([0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 0, 0, 0,
       0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0,
       1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3], dtype=int64), 
array([1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2,
       3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4,
       0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4], dtype=int64))
"""

另外,当我想统计形状的时候:

    print(np.nonzero(b3).shape)
AttributeError: 'tuple' object has no attribute 'shape'

这东西是个元祖,

bb = np.nonzero(b3)
print(len(bb))# 3
print(len(bb[0])) # 59
print(len(bb[1])) # 59
print(len(bb[2])) # 59
print(bb[0][1]) # 0

# print(len(bb[3])) # 59
# IndexError: tuple index out of range

注意,在结果里去每个array对应的位置就是非0值的位置啦~ 001,002,003都是非0的。

测试一下是否真的掌握了~

#a是1维数组
a = [0,2,3]
b = np.nonzero(a)
print(np.array(b).ndim)
print(b)

结果:
2
(array([1, 2], dtype=int64),)
说明:索引1和索引2的位置上元素的值非零。

#a是2维数组
a = np.array([[0,0,3],[0,0,0],[0,0,9]])
b = np.nonzero(a)
print(np.array(b).ndim)
print(b)
print(np.transpose(np.nonzero(a)))
结果:
2
(array([0, 2], dtype=int64), array([2, 2], dtype=int64))
[[0 2]
 [2 2]]
说明:
(1)a中有2个非零元素,因此,索引值tuple中array的长度为2。因为,只有非零元素才有索引值。
(2)索引值数组是2 维的。实际上,无论a的维度是多少,索引值数组一定是2维的tuple,但是tuple中的一维array个数和a的维数一致。
(3)第1个array([0, 2])是从row值上对3和9进行的描述
。第2个array([2, 2])是从col值上对3和9的描述。这样,从行和列上两个维度上各用一个数组来描述非零索引值。
(4)通过调用np.transpose()函数,得出3的索引值是[0 2]
,即第0行,第2列。


#a是3维数组
a = np.array([[[0,1],[1,0]],[[0,1],[1,0]],[[0,0],[1,0]]])
b = np.nonzero(a)
print(np.array(b).ndim)
print(b)
结果:
2
(array([0, 0, 1, 1, 2], dtype=int64), array([0, 1, 0, 1, 1], dtype=int64), array([1, 0, 1, 0, 0], dtype=int64))
说明:由于a是3维数组,因此,索引值数组有3个一维数组。
print(a)
[[[0 1]
  [1 0]]

 [[0 1]
  [1 0]]

 [[0 0]
  [1 0]]]
  a的数组结构如上所示,请将a想像为数量为3的一组小图片,每张图片的大小为2*2,下文中以num * row * col来分别表示其维度。
  b包含3个长度为5的array,这意味着a有3维,且a共有5个非0值。
  先说b中的第1个向量是[0, 0, 1, 1, 2],这实际是a在num维度上描述的非零值。第0张图上有2个非零值,第1张图上有2个非零值,第2张图上有1个非零值。因此在num维度上的非零值数组为[0, 0, 1, 1, 2]。
  b中的第2个向量是[0, 1, 0, 1, 1],这实际是a在row维度上描述的非零值。由于row上的值只有0和1(只2行),所以只由0和1组成。
  b中的第3个向量,聪明的读者可能已经明白,不再赘述。

原博下看到有人问三维矩阵,分析如下,注意绿色箭头所指的收集顺序

转载请注明出处!

参考:

python numpy中nonzero()的用法

一文详解numpy中np.nonzero()函数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值