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

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( )进行详细介绍。