像nonzero()这种比较常用的函数,在百度一搜就有一大把的解释和使用方法,但是喵哥却被网上丰富的资源搞晕了,后来经过喵哥一步一步的调试,总算看清了nonzero()的真实面目。为了以后可以再来看看,也为后来者不再被网上的解释搞糊涂,喵哥特地在此再说numpy.nonzero()函数。
事情的起始是这样的,喵哥在理解别人写的K-means时,遇到这么一句代码:
ptsInClust = dataSet[np.nonzero(clusterAssment[:,0].A == cent)[0]]
这句代码就用到了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中的非零值
总结的前三条把nonzero()的基本用法给说明白了,但是这种的使用方法并不可以完美的解释喵哥遇到的问题。
nonzero(clusterAssment[:,0].A == cent)里面的不是一个数组,而是一个表达式,表达式应该是与真假有关,为了进一步了解nonzero(),使用了help,发现还真有相关的描述:
A common use for ``nonzero`` is to find the indices of an array, where a condition is True.
那么,nonzero(a)的用法总结应该改一下:只有a为真值的元素才会有索引值。其余的说明是OK的。所以,
ptsInClust = dataSet[np.nonzero(clusterAssment[:,0].A == cent)[0]]
要表达的意思是:把clusterAssment[:,0].A中与cent(在代码中表示簇)一样的元素索引提取出来,又有nonzero()返回值是一个tuple,nonzero()[0]表示的是保证表达式为真值的元素位置的行坐标,然后利用这个行坐标提取出dataset对应的元素。
这样的解释也跟K-means的原理相符合:在聚类不满足介质条件时,还得求出每个簇的中心作为新的质心。
例子:
import numpy
#1.nonzero(python的简单序列对象)
a = [1,0,0,5,6,1,0,1]
b = numpy.nonzero(a)
print(b)
'''
输出:(array([0, 3, 4, 5, 7], dtype=int64),),其实就是一个包含一个array的tuple,如果取
b[0][1],会得到3.
'''
c = [[1,2,0],[5,0,1]]
d = numpy.nonzero(c)
print(d)
'''
输出:(array([0, 0, 1, 1], dtype=int64), array([0, 1, 0, 2], dtype=int64)),array([0, 0, 1, 1], dtype=int64)表示的是行坐标,array([0, 1, 0, 2], dtype=int64)表示的是列坐标
'''
#2.nonzero(python的表达式)
a = numpy.array([1,0,0,5,6,1,0,1])
b = numpy.nonzero(a > 1)
print(b)
'''
输出:(array([3, 4], dtype=int64),)
'''
c = numpy.array([[1,2,0],[5,0,1]])
d = numpy.nonzero(c == 1)
print(d)
'''
输出:(array([0, 1], dtype=int64), array([0, 2], dtype=int64))
'''