如何确定哪种分布最适合我的数据?


133

我有一个数据集,想找出哪种分布最适合我的数据。

我用了 fitdistr()函数来估计必要的参数,以描述假设的分布(即,威布尔,柯西,正态)。使用这些参数,我可以进行Kolmogorov-Smirnov检验来估计我的样本数据是否来自与假设分布相同的分布。

如果p值> 0.05,我可以假设样本数据是从相同的分布中得出的。但是p值没有提供有关拟合度的任何信息,不是吗?

因此,如果我的样本数据的p值对于正态分布以及Weibull分布> 0.05,那么我如何知道哪个分布更适合我的数据呢?

这基本上就是我所做的:

> mydata
 [1] 37.50 46.79 48.30 46.04 43.40 39.25 38.49 49.51 40.38 36.98 40.00
[12] 38.49 37.74 47.92 44.53 44.91 44.91 40.00 41.51 47.92 36.98 43.40
[23] 42.26 41.89 38.87 43.02 39.25 40.38 42.64 36.98 44.15 44.91 43.40
[34] 49.81 38.87 40.00 52.45 53.13 47.92 52.45 44.91 29.54 27.13 35.60
[45] 45.34 43.37 54.15 42.77 42.88 44.26 27.14 39.31 24.80 16.62 30.30
[56] 36.39 28.60 28.53 35.84 31.10 34.55 52.65 48.81 43.42 52.49 38.00
[67] 38.65 34.54 37.70 38.11 43.05 29.95 32.48 24.63 35.33 41.34

# estimate shape and scale to perform KS-test for weibull distribution
> fitdistr(mydata, "weibull")
     shape        scale   
   6.4632971   43.2474500 
 ( 0.5800149) ( 0.8073102)

# KS-test for weibull distribution
> ks.test(mydata, "pweibull", scale=43.2474500, shape=6.4632971)

        One-sample Kolmogorov-Smirnov test

data:  mydata
D = 0.0686, p-value = 0.8669
alternative hypothesis: two-sided

# KS-test for normal distribution
> ks.test(mydata, "pnorm", mean=mean(mydata), sd=sd(mydata))

        One-sample Kolmogorov-Smirnov test

data:  mydata
D = 0.0912, p-value = 0.5522
alternative hypothesis: two-sided

对于Weibull分布,p值为0.8669,对于正态分布,p值为0.5522。因此,我可以假设我的数据服从Weibull分布,而且服从正态分布。但是哪个分布函数可以更好地描述我的数据?


提到十一美元,我发现了以下代码,但不知道如何解释结果:

fits <- list(no = fitdistr(mydata, "normal"),
             we = fitdistr(mydata, "weibull"))
sapply(fits, function(i) i$loglik)
       no        we 
-259.6540 -257.9268 

5
您为什么要弄清楚哪种分布最适合您的数据?
罗兰

6
因为我想按照给定的分布生成伪随机数。
tobibo

6
您无法使用KS检查具有从数据集中找到的参数的分布是否与数据集匹配。例如,请参阅此页面上的#2 ,以及其他选择(以及KS测试可能会引起误解的其他方式)。
tpg2114

这里是代码示例的另一个讨论其中涉及从示例中估计参数时如何应用KS测试。
阿克萨卡(Aksakal)

1
I used the fitdistr() function .....什么fitdistr功能?来自Excel的东西?还是您在C语言中写过的东西?
Wolfies,2015年

Answers:


162

首先,这里有一些简短的评论:

  • p
  • p>0.05
  • 这里的目标不能是确定确定样本遵循什么分布。目标是@whuber(在注释中)调用数据的简约近似描述。具有特定的参数分布可以用作数据模型。

但是,让我们做一些探索。我将使用出色的fitdistrplus包装,它提供了一些很好的分布拟合功能。我们将使用该函数descdist获得有关可能的候选者分布的一些想法。

library(fitdistrplus)
library(logspline)

x <- c(37.50,46.79,48.30,46.04,43.40,39.25,38.49,49.51,40.38,36.98,40.00,
38.49,37.74,47.92,44.53,44.91,44.91,40.00,41.51,47.92,36.98,43.40,
42.26,41.89,38.87,43.02,39.25,40.38,42.64,36.98,44.15,44.91,43.40,
49.81,38.87,40.00,52.45,53.13,47.92,52.45,44.91,29.54,27.13,35.60,
45.34,43.37,54.15,42.77,42.88,44.26,27.14,39.31,24.80,16.62,30.30,
36.39,28.60,28.53,35.84,31.10,34.55,52.65,48.81,43.42,52.49,38.00,
38.65,34.54,37.70,38.11,43.05,29.95,32.48,24.63,35.33,41.34)

现在让我们使用descdist

descdist(x, discrete = FALSE)

Descdist

样品的峰度和偏度平方被绘制为蓝点,称为“观察”。似乎可能的分布包括Weibull,对数正态分布以及可能的Gamma分布。

让我们拟合一个威布尔分布和正态分布:

fit.weibull <- fitdist(x, "weibull")
fit.norm <- fitdist(x, "norm")

现在检查法线是否合适:

plot(fit.norm)

正常合身

对于威布尔拟合:

plot(fit.weibull)

威布尔飞度

两者看起来都不错,但根据QQ绘图判断,威布尔的外观可能更好一些,尤其是在尾部。相应地,与正常拟合相比,Weibull拟合的AIC较低:

fit.weibull$aic
[1] 519.8537

fit.norm$aic
[1] 523.3079

Kolmogorov-Smirnov测试模拟

我将使用此处说明的@Aksakal过程模拟null下的KS统计信息。

n.sims <- 5e4

stats <- replicate(n.sims, {      
  r <- rweibull(n = length(x)
                , shape= fit.weibull$estimate["shape"]
                , scale = fit.weibull$estimate["scale"]
  )
  estfit.weibull <- fitdist(r, "weibull") # added to account for the estimated parameters
  as.numeric(ks.test(r
                     , "pweibull"
                     , shape= estfit.weibull$estimate["shape"]
                     , scale = estfit.weibull$estimate["scale"])$statistic
  )      
})

模拟的KS统计量的ECDF如下所示:

plot(ecdf(stats), las = 1, main = "KS-test statistic simulation (CDF)", col = "darkorange", lwd = 1.7)
grid()

模拟的KS统计

p

fit <- logspline(stats)

1 - plogspline(ks.test(x
                       , "pweibull"
                       , shape= fit.weibull$estimate["shape"]
                       , scale = fit.weibull$estimate["scale"])$statistic
               , fit
)

[1] 0.4889511

这证实了我们的图形结论,即样本与Weibull分布兼容。

正如解释在这里,我们可以使用自举逐点置信区间添加到估计威布尔PDF或CDF:

xs <- seq(10, 65, len=500)

true.weibull <- rweibull(1e6, shape= fit.weibull$estimate["shape"]
                         , scale = fit.weibull$estimate["scale"])

boot.pdf <- sapply(1:1000, function(i) {
  xi <- sample(x, size=length(x), replace=TRUE)
  MLE.est <- suppressWarnings(fitdist(xi, distr="weibull"))  
  dweibull(xs, shape=MLE.est$estimate["shape"],  scale = MLE.est$estimate["scale"])
}
)

boot.cdf <- sapply(1:1000, function(i) {
  xi <- sample(x, size=length(x), replace=TRUE)
  MLE.est <- suppressWarnings(fitdist(xi, distr="weibull"))  
  pweibull(xs, shape= MLE.est$estimate["shape"],  scale = MLE.est$estimate["scale"])
}
)   

#-----------------------------------------------------------------------------
# Plot PDF
#-----------------------------------------------------------------------------

par(bg="white", las=1, cex=1.2)
plot(xs, boot.pdf[, 1], type="l", col=rgb(.6, .6, .6, .1), ylim=range(boot.pdf),
     xlab="x", ylab="Probability density")
for(i in 2:ncol(boot.pdf)) lines(xs, boot.pdf[, i], col=rgb(.6, .6, .6, .1))

# Add pointwise confidence bands

quants <- apply(boot.pdf, 1, quantile, c(0.025, 0.5, 0.975))
min.point <- apply(boot.pdf, 1, min, na.rm=TRUE)
max.point <- apply(boot.pdf, 1, max, na.rm=TRUE)
lines(xs, quants[1, ], col="red", lwd=1.5, lty=2)
lines(xs, quants[3, ], col="red", lwd=1.5, lty=2)
lines(xs, quants[2, ], col="darkred", lwd=2)

CI_密度

#-----------------------------------------------------------------------------
# Plot CDF
#-----------------------------------------------------------------------------

par(bg="white", las=1, cex=1.2)
plot(xs, boot.cdf[, 1], type="l", col=rgb(.6, .6, .6, .1), ylim=range(boot.cdf),
     xlab="x", ylab="F(x)")
for(i in 2:ncol(boot.cdf)) lines(xs, boot.cdf[, i], col=rgb(.6, .6, .6, .1))

# Add pointwise confidence bands

quants <- apply(boot.cdf, 1, quantile, c(0.025, 0.5, 0.975))
min.point <- apply(boot.cdf, 1, min, na.rm=TRUE)
max.point <- apply(boot.cdf, 1, max, na.rm=TRUE)
lines(xs, quants[1, ], col="red", lwd=1.5, lty=2)
lines(xs, quants[3, ], col="red", lwd=1.5, lty=2)
lines(xs, quants[2, ], col="darkred", lwd=2)
#lines(xs, min.point, col="purple")
#lines(xs, max.point, col="purple")

CI_CDF


使用GAMLSS进行自动分配拟合

gamlssRfitDisttype = "realline"type = "realsplus"kk=2klog(n)

library(gamlss)
library(gamlss.dist)
library(gamlss.add)

x <- c(37.50,46.79,48.30,46.04,43.40,39.25,38.49,49.51,40.38,36.98,40.00,
       38.49,37.74,47.92,44.53,44.91,44.91,40.00,41.51,47.92,36.98,43.40,
       42.26,41.89,38.87,43.02,39.25,40.38,42.64,36.98,44.15,44.91,43.40,
       49.81,38.87,40.00,52.45,53.13,47.92,52.45,44.91,29.54,27.13,35.60,
       45.34,43.37,54.15,42.77,42.88,44.26,27.14,39.31,24.80,16.62,30.30,
       36.39,28.60,28.53,35.84,31.10,34.55,52.65,48.81,43.42,52.49,38.00,
       38.65,34.54,37.70,38.11,43.05,29.95,32.48,24.63,35.33,41.34)

fit <- fitDist(x, k = 2, type = "realplus", trace = FALSE, try.gamlss = TRUE)

summary(fit)

*******************************************************************
Family:  c("WEI2", "Weibull type 2") 

Call:  gamlssML(formula = y, family = DIST[i], data = sys.parent()) 

Fitting method: "nlminb" 


Coefficient(s):
             Estimate  Std. Error  t value   Pr(>|t|)    
eta.mu    -24.3468041   2.2141197 -10.9962 < 2.22e-16 ***
eta.sigma   1.8661380   0.0892799  20.9021 < 2.22e-16 ***

根据AIC,Weibull分布(更具体地说WEI2,是它的特殊参数化)最适合数据。该文档的确切参数化在第279页上的文档中进行了WEI2详细说明。让我们通过查看蠕虫图中的残差(基本上是去趋势的QQ图)来检查拟合度:

蠕虫图

我们期望残差接近中间水平线,并且其中95%的残差位于上下虚线之间,这是95%的逐点置信区间。在这种情况下,蠕虫图对我来说看起来很好,表明Weibull分布很合适。


1
+1不错的分析。不过,有一个问题。关于与特定主要分布(在这种情况下为Weibull)的兼​​容性的肯定结论是否可以排除存在混合物分布的可能性?还是我们需要执行适当的混合分析并检查GoF以排除该选项?
Aleksandr Blekh

18
@AleksandrBlekh不可能有足够的能力来排除混合物:当混合物具有两种几乎相同的分布时,就无法检测到;而除了一种成分之外,所有成分都占很小比例时,也无法检测到。通常(在缺乏可能暗示分布形式的理论的情况下),为了满足对数据的简约近似描述,需要对参数分布进行拟合。混合物不是其中的一种:它们需要太多的参数并且灵活了。
whuber

4
@whuber:+1感谢您的出色解释!
Aleksandr Blekh,2015年

1
@Lourenco我看了Cul​​len and Fey图。蓝点表示我们的样本。您会看到该点接近Weibull,对数正态和Gamma(在Weibull和Gamma之间)的线。在拟合了每个分布之后,我使用函数gofstat和AIC 比较了拟合优度统计数据。确定“最佳”分布的最佳方法是什么还没有达成共识。我喜欢图形方法和AIC。
COOLSerdash

1
@Lourenco您的意思是对数正态吗?逻辑分布(“ +”号)与观察到的数据有很大距离。对数正态也将是我通常会看的候选对象。在本教程中,为了保持简短,我选择不显示它。与Weibull分布和正态分布相比,对数正态分布的拟合度较差。AIC为537.59,图表看起来也不太好。
COOLSerdash

15

绘图通常是一种更好地了解数据外观的好方法。在您的情况下,我建议绘制经验累积分布函数您使用从fitdistr()获得的参数,针对理论cdfs(ecdf)。

我为数据做过一次,还包括置信区间。这是我使用ggplot2()获得的图片。

在此处输入图片说明

黑线是经验累积分布函数,而彩色线是使用最大似然法得到的参数来自不同分布的cdfs。可以很容易地看出,指数分布和正态分布都不适合数据,因为这些行的形式与ecdf不同,并且这些行与ecdf相距很远。不幸的是,其他分布非常接近。但是我要说的是logNormal线最接近黑线。使用距离的度量(例如MSE)可以验证该假设。

如果您只有两个竞争分布(例如,选择在图中最合适的分布),则可以使用似然比测试来测试哪个分布更合适。


20
欢迎来到CrossValidated!如果您可以对其进行编辑以包含(a)用于生成图形的代码,以及(b)如何读取图形的答案,则答案可能会更有用。
Stephan Kolassa,2015年

2
那里正在绘制什么?那是某种指数图吗?
Glen_b 2015年

1
但是,您如何确定哪种分布最适合您的数据呢?仅根据图形,我无法告诉您logNormal或weibull是否最适合您的数据。
tobibo

4
如果要创建伪随机数生成器,为什么不使用经验CDF?您想绘制超出观察分布的数字吗?
十一美元2015年

6
以图的面值计算,似乎所有候选分布都无法很好地拟合数据。另外,您的ecdf似乎具有小于0.03的水平渐近线,这是没有意义的,因此我不确定它最初是否真的是ecdf。
Hong Ooi 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.