
2.4.4 统计函数
与本节内容对应的Notebook为:02-numpy/numpy-420-functions-count.ipynb。
本节介绍的函数如表2-6所示。
表2-6 本节要介绍的函数

unique()返回其参数数组中所有不同的值,并且按照从小到大的顺序排列。它有两个可选参数:
●return_index:Ture表示同时返回原始数组中的下标。
●return_inverse:True表示返回重建原始数组用的下标数组。
下面通过几个例子介绍unique()的用法。首先用randint()创建有10个元素、值在0到9范围之内的随机整数数组,通过unique(a)可以找到数组a中所有的整数,并按照升序排列:
np.random.seed(42) a = np.random.randint(0, 8, 10) a np.unique(a) ------------------------------ ------------------ [6, 3, 4, 6, 2, 7, 4, 4, 6, 1] [1, 2, 3, 4, 6, 7]
如果参数return_index为True,则返回两个数组,第二个数组是第一个数组在原始数组中的下标。在下面的例子中,数组index保存的是数组x中每个元素在数组a中的下标:
x, index = np.unique(a, return_index=True) x index a[index] ------------------ ------------------ ------------------ [1, 2, 3, 4, 6, 7] [9, 4, 1, 2, 0, 5] [1, 2, 3, 4, 6, 7]
如果参数return_inverse为True,则返回的第二个数组是原始数组a的每个元素在数组x中的下标:
x, rindex = np.unique(a, return_inverse=True) rindex x[rindex] ------------------------------ ------------------------------ [4, 2, 3, 4, 1, 5, 3, 3, 4, 0] [6, 3, 4, 6, 2, 7, 4, 4, 6, 1]
bincount()对整数数组中各个元素所出现的次数进行统计,它要求数组中的所有元素都是非负的。其返回数组中第i个元素的值表示整数i出现的次数。
np.bincount(a) array([0, 1, 1, 1, 3, 0, 3, 1])
由上面的结果可知,在数组a中有1个1、1个2、1个3、3个4、3个6和1个7,而0、5等数没有在数组a中出现。
通过weights参数可以指定每个数所对应的权值。当指定weights参数时,bincount(x, weights=w)返回数组x中的每个整数所对应的w中的权值之和。用文字解释比较难以理解,下面我们看一个实例:
x = np.array([0 , 1, 2, 2, 1, 1, 0]) w = np.array([0.1, 0.3, 0.2, 0.4, 0.5, 0.8, 1.2]) np.bincount(x, w) array([ 1.3, 1.6, 0.6])
在上面的结果中,1.3是数组x中0所对应的w中的元素(0.1和1.2)之和,1.6是1所对应的w中的元素(0.3、0.5和0.8)之和,而0.6是2所对应的w中的元素(0.2和0.4)之和。如果要求平均值,可以用求和的结果与次数相除:
np.bincount(x, w) / np.bincount(x) array([ 0.65 , 0.53333333, 0.3 ])
histogram()对一维数组进行直方图统计。其参数列表如下:
histogram(a, bins=10, range=None, weights=None, density=False)
其中a是保存待统计数据的数组,bins指定统计的区间个数,即对统计范围的等分数。range是一个长度为2的元组,表示统计范围的最小值和最大值,默认值为None,表示范围由数据的范围决定,即(a.min(), a.max())。当density参数为False时,函数返回a中的数据在每个区间的个数,参数为True则返回每个区间的概率密度。weights参数和bincount()的类似。
histogram()返回两个一维数组—— hist和bin_edges,第一个数组是每个区间的统计结果,第二个数组的长度为len(hist) + 1,每两个相邻的数值构成一个统计区间。下面我们看一个例子:
a = np.random.rand(100) np.histogram(a, bins=5, range=(0, 1)) (array([28, 18, 17, 19, 18]), array([ 0. , 0.2, 0.4, 0.6, 0.8, 1. ]))
首先创建了一个有100个元素的一维随机数组a,取值范围在0到1之间。然后用histogram()对数组a中的数据进行直方图统计。结果显示有28个元素的值在0到0.2之间,18个元素的值在0.2到0.4之间。读者可以尝试用rand()创建更大的随机数组,由统计结果可知每个区间出现的次数近似相等,因此rand()所创建的随机数在0到1范围之间是平均分布的。
如果需要统计的区间的长度不等,可以将表示区间分隔位置的数组传递给bins参数,例如:
np.histogram(a, bins=[0, 0.4, 0.8, 1.0]) (array([46, 36, 18]), array([ 0. , 0.4, 0.8, 1. ]))
结果表示0到0.4之间有46个值,0.4到0.8之间有36个值。
如果用weights参数指定了数组a中每个元素所对应的权值,则histogram( )对区间中数值所对应的权值进行求和。下面看一个使用histogram( )统计男性青少年年龄和身高的例子。“height.csv”文件是100名年龄在7到20岁之间的男性青少年的身高统计数据。
首先用loadtxt( )从数据文件载入数据。在数组d中,第0列是年龄,第1列是身高。可以看到年龄的范围在7到20之间:

下面对数据进行统计,sums是每个年龄段的身高总和,cnts是每个年龄段的数据个数,因此很容易计算出每个年龄段的平均身高:

histogram2d( )和histogramdd( )对二维和N维数据进行直方图统计,我们将在第9章介绍OpenCV时对histogram2d( )进行详细介绍。