如何使Weibull分布适合包含零的输入数据?


14

我正在尝试重现由退休研究员传承的现有预测算法。第一步是将一些观察到的数据拟合为威布尔分布,以获得将用于预测未来值的形状和比例。我正在用R做到这一点。这是我的代码示例:

x<-c(23,19,37,38,40,36,172,48,113,90,54,104,90,54,157,51,77,78,144,34,29,45,16,15,37,218,170,44,121)
f<-fitdistr(x, 'weibull')

除非输入数组中有任何零,否则它将完全失败,这可以正常工作。SAS中也会发生同样的事情。据我了解,这是因为计算Weibull分布的步骤之一是采用自然对数,该自然对数未定义为0。是否有合理的方法来解决此问题?

到目前为止,我发现最好的方法是在所有输入值中加1,拟合曲线,然后从预测值中减去1(“上移”曲线,然后下移1)。这非常适合先前预测的数据,但是这样做似乎是错误的方法。

编辑:输入数组中的值是多年来观察到的真实数据(某物的出现次数)。因此,在某些年份中发生的次数为零。不管这是不是最好的方法(我同意可能不是),原始算法作者声称已经使用了Weibull分布,并且我不得不尝试复制他们的过程。


5
威布尔是一个连续分布,因此正好为零的概率为零。如果您的数据中有很多零,那么这直接表明威布尔不合适。无论如何,您的数据看起来都像计数数据(或至少是离散数据),因此Weibull可能不是最佳选择。
红衣主教

添加一些有关数据来自何处的上下文,将有助于任何试图做出巨大回答的人。
红衣主教

Answers:


8

(正如其他人指出的那样,当数据仅是整数时,Weibull分布不太可能是合适的近似值。以下内容仅用于帮助您确定以前的研究人员是对还是错。

有几种不受数据零影响的替代方法,例如使用各种矩量估计器。这些通常需要涉及伽马函数的方程的数值解,因为威布尔分布的矩是根据该函数给出的。我不熟悉R,但是这里有一个Sage程序,它说明了一种更简单的方法-也许它可以适应R?(您可以在Horst Rinne撰写的“ Weibull发行:一本手册”,第455ff页中阅读有关此方法和其他此类方法的信息;但是,他的等式12.4b中有一个错字,即“ -1”是多余的)。

"""
Blischke-Scheuer method-of-moments estimation of (a,b)
for the Weibull distribution F(t) = 1 - exp(-(t/a)^b)
""" 

x = [23,19,37,38,40,36,172,48,113,90,54,104,90,54,157,
      51,77,78,144,34,29,45,16,15,37,218,170,44,121]
xbar = mean(x)
varx = variance(x)
var("b"); f(b) = gamma(1+2/b)/gamma(1+1/b)^2 - 1 - varx/xbar^2
bhat = find_root(f, 0.01, 100)
ahat = xbar/gamma(1+1/bhat)
print "Estimates: (ahat, bhat) = ", (ahat, bhat)

这产生了输出

Estimates: (ahat, bhat) =  (81.316784310814455, 1.3811394719075942)


0

x = [23,0,37,38,40,36,172,48,113,90,54,104,90,54,157,
      51,77,78,144,34,29,45,0,0,37,218,170,44,121]

然后相同的过程产生输出

Estimates: (ahat, bhat) =  (78.479354097488923, 1.2938352346035282)


编辑:我刚刚安装R来尝试一下。冒着使这个答案冗长的风险,对于有兴趣的人,这是我的Blischke-Scheuer方法的R代码:

fit_weibull <- function(x)
{
    xbar <- mean(x)
    varx <- var(x)
    f <- function(b){return(gamma(1+2/b)/gamma(1+1/b)^2 - 1 - varx/xbar^2)}
    bhat <- uniroot(f,c(0.02,50))$root
    ahat <- xbar/gamma(1+1/bhat)
    return(c(ahat,bhat))
}

这重现了上述两个Sage示例(至五个有效数字):

x <- c(23,19,37,38,40,36,172,48,113,90,54,104,90,54,157,
     51,77,78,144,34,29,45,16,15,37,218,170,44,121)
fit_weibull(x)
[1] 81.316840  1.381145

x <- c(23,0,37,38,40,36,172,48,113,90,54,104,90,54,157,
      51,77,78,144,34,29,45,0,0,37,218,170,44,121)
fit_weibull(x)
[1] 78.479180  1.293821

4

θfitdistrθθfitdistr

foo <- function(theta, x)
{
  if (theta <= -min(x)) return(Inf);
  f <- fitdistr(x+theta, 'weibull')
  -2*f$loglik
}

然后使用一维优化最小化此函数:

bar <- optimize(foo, lower=-min(x)+0.001, upper=-min(x)+10, x=x)

我刚刚什么都没补上“ +10”。

对于将三个最小值替换为零的数据,我们得到:

> bar
$minimum
[1] 2.878442

$objective
[1] 306.2792

> fitdistr(x+bar$minimum, 'weibull')
     shape        scale   
   1.2836432   81.1678283 
 ( 0.1918654) (12.3101211)
> 

bar$minimumθfitdistrθ


2

它应该失败,您应该感谢它失败了。

您的观察结果表明,故障是在您开始观察故障的那一刻发生的。如果这是一个真实的过程,来自真实的(而不是模拟的数据),则需要以某种方式解释为什么得到零的原因。我见过生存研究,其中由于以下几种原因之一而出现0次:

  1. 数据实际上被截断了:在研究开始之前,对象有危险并且发生了故障,您想假装一直观察到它们。
  2. 仪器校准不良:您的测量精度不足以进行研究,因此在开始时间附近发生的故障被编码为恰好为零。
  3. 编码为零的事物不是零。他们是被一种或另一种方式排除在分析之外的人或物体。由于合并,排序或以其他方式重新编码缺失值,因此数据中仅显示零。

因此,对于情况1:即使需要追溯提取记录,也需要使用适当的检查方法。情况2意味着您可以使用EM算法,因为您存在精度问题。贝叶斯方法在这里也类似地工作。情况3意味着您只需要排除应该丢失的值。


OP解释说,以前的研究人员选择拟合Weibull分布,即使数据是真实计数 -某物出现次数的非负整数计数也是如此。目前尚不清楚您的三个案例与这种情况有何关系。
res

哦,请注意!拟合Weibull分布非常错误。它具有持续的支持,从未用于建模计数,而是用于生存时间。负二项式分布将是一种用于建模计数的等效的两个参数分布,这当然取决于数据生成过程的性质(正如问题所指出的,我们拥有0个信息)。感谢您向我指出。
AdamO 2011年

1

我同意上述枢机主教的回答。但是,添加常量以避免零也是很常见的。另一个常用的值为0.5,但是可能使用了任何正常数。您可以尝试一系列值,以查看是否可以确定以前的研究人员使用的确切值。然后,您可以确信,在继续寻找更好的发行版本之前,您可以复制他的结果。


0

[假设使用Weibull是合适的] Johnson Kotz和Balakrishnan的书中有很多估算Weibull参数的方法。其中一些不依赖于不包括零的数据(例如,使用均值和标准差,或使用某些百分位数)。

约翰逊(NL),科兹(S. Kotz)和新北巴拉克拉南(Balakrishnan)(1994)。连续单变量分布。纽约:威利,大约在632页。

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.