5.2 连续随机变量分布

SciPy包含了大量的处理连续随机变量的函数,每种函数都位于与其对应的分布类中。每个类都有对应的方法来生成随机数,从而计算PDF、CDF,使用MLE进行参数估计,以及矩估计等。相应的方法将在下文中详细讲解,其中,dist代表了SciPy中相应的分布名称,每种分布除了自身特殊的输入变量之外,还包含三种常用的参数,具体说明如下。

·*args:表示每个分布定义所需的参数。例如,使用F分布的时候,需要两个参数。第一个参数是分子自由度。第二个参数是分母自由度。

·loc:表示位置参数,用于决定分布的中心位置。

·scale:表示比例参数,用于决定分布的缩放比例。例如,假设z是标准的正态分布,那么s×x就是一个缩放s倍的标准正态分布。

5.2.1 分布的基本特征

SciPy能够生成各种满足不同分布的随机数。

1.dist.rvs

dist.rvs是伪随机数生成函数,一般调用方法为dist.rvs(*args,loc=0,scale=1,size=size)。其中,size是一个n维数据,决定了所生成数组的大小。示例代码如下:


from scipy import stats 
a = stats.chi2(10).rvs(1000)
plt.hist(a,bins = 50)

运行结果如图5-8所示。

图 5-8

我们来考察一下分布的一些基本特征。

2.dist.pdf

dist.pdf是指对一组数据估计出来的概率密度函数,一般调用方法为dist.pdf(x,*args,loc=0,scale=1)。其中,x是用来进行估计的数组。示例代码如下:


stats.norm(0,1).pdf(0)
Out[49]: 0.3989422804014327

3.dist.logpdf

dist.logpdf是指对一组数据估计出来的对数概率密度函数,一般调用方法为dist.logpdf(x,*args,loc=0,scale=1),其中,x是用来进行估计的数组。示例代码如下:


stats.norm(0,1).logpdf(0)
Out[50]: -0.9189385332046727

4.dist.cdf

dist.cdf是指对一组数据估计出来的累积分布函数,一般调用方法为dist.cdf(x,*args,loc=0,scale=1),其中,x是用来进行估计的数组。示例代码如下:


stats.norm(0,1).cdf(2)
Out[54]: 0.9772498680518208

5.dist.ppf

dist.ppf是指对于一组范围为0到1的数据,估计出来的累积分布函数的反函数,一般调用方法为dist.ppf(p,*args,loc=0,scale=1),其中,p是所有元素均为0到1之间数据的数组。示例代码如下:


stats.norm(0,1).ppf(0.618)
Out[55]: 0.30023225938072184

6.dist.fit

对于一组数据,使用最大似然法估计出其形状、位置及比例参数,一般调用方法为dist.fit(data,*args,f?loc=0,fscale=1),其中,data是用来估计参数的数据;floc用于强制规定location的取值;fscale用于强制规定scale的取值。在使用最大似然估计的时候,如果分布没有location和scale,那么一般有必要强制规定一个取值。

下面来看一个示例,首先生成10000个自由度为10的卡方分布模拟数据,代码如下:


a = stats.chi2(10).rvs(10000)

然后利用MLE进行拟合,代码如下:


stats.chi2.fit(a)
Out[58]: (10.258104233623369, -0.11014565203039026, 0.9850494177711357)

在获得的结果当中,数组的第一个数为卡方分布的自由度估计,第二个第三个为中心值和scale。

7.dist.mean

dist.mean用于返回分布的均值,一般调用方法为dist.mean(*args,loc=0,scale=1)。示例代码如下:


stats.beta(1,2).mean()
Out[60]: 0.3333333333333333

8.dist.median

dist.median用于返回分布的中位数,一般调用方法为dist.mean(*args,loc=0,scale=1)。示例代码如下:


stats.chi2(10).median()
Out[61]: 9.34181776559197

9.dist.var

dist.var用于返回分布的方差,一般调用方法为dist.var(*args,loc=0,scale=1)。示例代码如下:


stats.chi2(10).var()
Out[73]: 20.0

10.dist.std

dist.std用于返回分布的标准差,一般调用方法为dist.std(*args,loc=0,scale=1)。示例代码如下:


stats.chi2(10).std()
Out[74]: 4.47213595499958

5.2.2 衍生特征

1.偏度

skewness代表分布的偏度特征,偏度描述的是一个分布的“不对称性”,其计算公式为:

为了理解不对称性,我们先来看几个对称分布,示例代码如下:


import seaborn as sns
import numpy as np
x = np.random.normal(size=10000)
sns.distplot(x)
Out[65]: <matplotlib.axes._subplots.AxesSubplot at 0x277cbf32908>

画出相应的图,如图5-9所示。

图 5-9

可以看到,标准正态分布是以y轴为中心对称的,并且分布的平均数与标准差分别为0和1。很显然,对于标准正态分布而言,分布的偏度等于其三阶矩,我们用Scipy的dist.moment函数即可获得其偏度。

返回分布的n阶中心矩,一般的调用方法为dist.moment(r,*args),其中,r是需要计算的矩的阶数。示例代码如下:


stats.norm().moment(3)
Out[66]: 0.0

再来看另外一个例子,卡方分布,示例代码如下:


import seaborn as sns
import numpy as np
x = stats.chi2(10).rvs(100000) 
sns.distplot(x)
Out[67]: <matplotlib.axes._subplots.AxesSubplot at 0x277ca44add8>

画出相应的图,如图5-10所示。

图 5-10

很明显,分布并不是中心对称的。

下面来计算一下其偏度,示例代码如下:


stats.skew(stats.chi2(10).rvs(100000))
Out[71]: 0.8891063018810491

2.kurtosis峰度

峰度描述的是分布函数在平均值位置的取值高低的统计量。峰值高低是相对于标准正态分布的平均值而言的。一般定义正态分布的峰度为0。为了满足这一定义,计算峰度的公式如下:

感兴趣的读者可以计算一下标准正态分布的峰度(提示:利用moment generating function可以很轻易地得出标准正态分布的各阶中心矩)。

下面来看一个典型的比正态分布峰值相对更高的分布:拉普拉斯分布(Laplace Distribution)。示例代码如下:


x = stats.laplace(loc = 0, scale = 1).rvs(10000)
sns.distplot(x)

画出相应的图,如图5-11所示。

图 5-11

下面就来生成大量的随机数,来估计一下在相同loc和scale的情况下,拉普拉斯分布与正态分布的峰值,示例代码如下:


x = stats.laplace(loc = 0, scale = 1).rvs(10000)
stats.kurtosis(x)
Out[85]: 3.245024800904149

y = stats.norm(loc = 0, scale = 1).rvs(10000)
stats.kurtosis(y)
Out[86]: -0.00889987923437019