强基初中数学&学Python——第221课 数字和数学模块之六:statistics——数学统计函数(3)

statistics.quantiles(data, *, n=4, method='exclusive')   data 分隔为具有相等概率的 n 个连续区间。返回分隔这些区间的 n - 1 个分隔点的列表。特殊参数(*)后的形参只能用关键字输入。  n设为4,则分4个相等的区间(默认值)。  n设为6,则分6个相等的区间。  如果n=1,这函数不需要干什么,直接返回空列表。  如果n<1,则将引发StatisticsError。  如果数据项的个数小于2则将引发StatisticsError。  分隔点是通过对两个最接近的数据项进行线性插值得到的。插值方法与method参数有关。method参数可取2个值:exclusive(不包括,默认值)和inclusive(包括)method='exclusive'时(默认),采用正比例插值,即左右长度比等于左右段数比;method='inclusive'时,采用反比例插值,即左右长度比等于右左段数比:  p=p1+(p2-p1)×(m/n)  (method='exclusive'),  ①
  p=p1+(p2-p1)×[(n-m)/n]  (method='inclusive'),  ②  p是插值点,  p1是低点,  p2是高点,  m是第几个插入点(1开始),  n是分段数。  把[1,2,3,4,5,6,7,8,9,10,11,12]分四段,代入上面的公式,得到结果:[3.25, 6.5, 9.75] (method='exclusive'),[3.75, 6.5, 9.25] method='inclusive')。
  验证:
  把②式变换一下就变成:  p=p2 - (p2-p1)×(m/n),也就是说,method='inclusive'时,分割点是从右点往左走正比例的长度。  data可以是包含样本数据的任意可迭代对象。为了获得有意义的结果,data中数据项的数量应当大于n。  至于采用哪种method,由输入的数据data是包含(includes)还是排除(excludes)总体的最低和最高可能值而定。包含(includes)用method='inclusive';排除(excludes)用method='exclusive'。  当总体数据中能找到比样品数据中最小值更小、或比样品数据中最大值更大的数据项时,采用method='exclusive'。对于一个已经排好序的m个数据项的序列,i个数据项(从1开始)的积累概率:SP=i/(m+1)。(i从1开始)
比如,九个已排好序的样本数据:[1,2,4,8,16,32,64,128,256],根据上面的公式,可以计算出各个数据项对应的概率(百分数):
[10%,20%,30%,40%,50%,60%,70%,80%,90%]。
  可见,最后一个数据项的积累概率不是100%。
  当样品数据中已包含总体的最大最小值,采用method='inclusive'。数据中的最小值的积累概率被认为是0,而最大值是1。对于一个已经排好序的m个数据项的序列,i个数据项(从1开始)的积累概率:SP=(i-1)/(m-1)。(i从1开始)比如,11个已排好序的样本数据:[1,2,4,8,16,32,64,128,256,512,1024],根据上面的公式,可以计算出各个数据项对应的概率(百分数):
[0%,10%,20%,30%,40%,50%,60%,70%,80%,90%,100%]。
  可见,最后一个数据项的积累概率是100%。  不管哪一种,最后还是用最后一个数据项的积累概率为等分总概率。  最后,用官方文档上的数据,进行quantiles函数的模拟测试,代码(文本代码附录1)和运行结果如下:  可见,文中对quantiles函数的算法描述完全正确。
附录1:

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

#statistic.quantiles 测试from statistics import quantilesdata = [105, 129, 87, 86, 111, 111, 89, 81, 108, 92, 110,        100, 75, 105, 103, 109, 76, 119, 99, 91, 103, 129,        106, 101, 84, 111, 74, 87, 86, 103, 103, 106, 86,        111, 75, 87, 102, 121, 111, 88, 89, 101, 106, 95,        103, 107, 101, 81, 109, 104]      n=10  #分区数print("method='exclusive'测试:")print("函数调用:")print([round(q, 1) for q in quantiles(data, n=n)]) dt = sorted(data)  #数据排序m = len(dt)  #数据个数print("模拟测试:")P = m/(m+1)  #总概率,最后一个数据项的概率UP = P/n  #每区的概率rstEx = []  #分割点列表k = 1for i in range(m-1):    if k == n:        break          node = dt[i]    nextNode = dt[i+1]    if (i+2)/(m+1) > k * UP:  #nextNode已过分割点        rstEx.append(node + (nextNode-node)*k/n)        k+=1print([round(q, 1) for q in rstEx])print("method='inclusive'测试:")print("函数调用:")print([round(q, 1) for q in quantiles(data, n=n, method='inclusive')])  print("模拟测试:")P = 1  #总概率,最后一个数据项的概率UP = P/n  #每区的概率rstIn = []  #分割点列表k = 1for i in range(m-1):    if k == n:        break          node = dt[i]    nextNode = dt[i+1]    if (i+1)/(m-1) > k * UP:  #nextNode已过分割点        rstIn.append(node + (nextNode-node)*(n-k)/n)        k+=1print([round(q, 1) for q in rstIn])