在哪里定义与fitdist(fitdistrplus)或fitdistr(MASS)一起使用的分布函数?

时间:2014-07-24 13:12:16

标签: r distribution environment

我想定义自己的分布函数,用于R中的fitdist或fitdistr函数。 以fitdistrplus包中的fitdist为例。我定义了一个名为sgamma的自定义发行版,如下所示:

dsgamma<-function(x,shape){return(dgamma(x,shape,scale=1));}
qsgamma<-function(p,shape){return(qgamma(p,shape,scale=1));}
psgamma<-function(q,shape){return(pgamma(q,shape,scale=1));}
rsgamma<-function(n,shape){return(rgamma(n,shape,scale=1));}

我的问题是我应该定义这些功能。

如果上面的定义和声明是在顶级环境中进行的,那么我可以使用此分发函数调用fitdist。换句话说,我的脚本test1.R与以下内容将运行正常:

rm(list=ls())
require(fitdistrplus);
dsgamma<-function(x,shape){return(dgamma(x,shape,scale=1));}
qsgamma<-function(p,shape){return(qgamma(p,shape,scale=1));}
psgamma<-function(q,shape){return(pgamma(q,shape,scale=1));}
rsgamma<-function(n,shape){return(rgamma(n,shape,scale=1));}
x<-rgamma(100, shape=0.4, scale=1);
zfit<-fitdist(x, distr=dsgamma, start=list(shape=0.3));

现在,如果我将上述代码包装在一个函数中,它就不起作用了。见下面的test2.R:

rm(list=ls())
testfit<-function(x)
{
    require(fitdistrplus);
    dsgamma<-function(x,shape){return(dgamma(x,shape,scale=1));}
    qsgamma<-function(p,shape){return(qgamma(p,shape,scale=1));}
    psgamma<-function(q,shape){return(pgamma(q,shape,scale=1));}
    rsgamma<-function(n,shape){return(rgamma(n,shape,scale=1));}
    zfit<-fitdist(x, distr=dsgamma, start=list(shape=0.3));
    return(zfit);
}

x<-rgamma(100, shape=0.4, scale=1);
zfit<-testfit(x);

我收到以下错误:

Error in fitdist(x, distr = dsgamma, start = list(shape = 0.3)) : 
  The  dsgamma  function must be defined

请注意,如果我替换

,我仍会收到错误消息
zfit<-fitdist(x, distr=dsgamma, start=list(shape=0.3));

zfit<-fitdist(x, distr="sgamma", start=list(shape=0.3));

我猜关键问题是fitdist在哪里查找参数distr指定的函数。我非常感谢你的帮助。

1 个答案:

答案 0 :(得分:3)

好问题。出现此错误的原因是fitdistrplus包的作者使用exists()来检查函数所需参数的变体。

以下是fitdistmledist函数代码的摘录。作者采用distr给出的值,并在全球环境和定义fitdistmledist的环境中搜索适当的密度和概率函数。

if (!exists(ddistname,mode="function"))
    stop(paste("The ", ddistname, " function must be defined"))
pdistname <- paste("p", distname, sep = "")
if (!exists(pdistname,mode="function"))
    stop(paste("The ", pdistname, " function must be defined"))

这是有效存在的摘录:

此函数查看名称“x”是否具有绑定到它的值      在指定的环境中。 如果'inherits'是'TRUE'和值      找不到指定环境中的'x',封闭      搜索环境的帧直到名称“x”为止      遇到。参见'环境'和'R语言定义'      有关环境结构及其结构的详细信息,请参见手册      外壳

要了解有关原因存在的更多信息,请查看以下文章:http://adv-r.had.co.nz/Environments.html

基本上,fitdist和mledist不会在您正在创建的函数的环境中进行搜索,从而导致dsgamma(以及您定义的其他函数)不存在的错误。

使用<<-代替<-来定义testfit()中的函数,可以最容易地规避这一点。这将全局定义您的子功能。

 > testfit<-function(x)
 +     {
 +             require(fitdistrplus);
 +                 dsgamma<<-function(x,shape){return(dgamma(x,shape,scale=1))}
 +                 qsgamma<<-function(p,shape){return(qgamma(p,shape,scale=1))}
 +                 psgamma<<-function(q,shape){return(pgamma(q,shape,scale=1))}
 +                 rsgamma<<-function(n,shape){return(rgamma(n,shape,scale=1))}
 +                 zfit<-function(x){return(fitdist(x,distr="sgamma" , start=list(shape=0.3)))};
 +                 return(zfit(x))
 +         }
!> testfit(x)
 Fitting of the distribution ' sgamma ' by maximum likelihood
 Parameters:
       estimate Std. Error
 shape 0.408349 0.03775797

您可以通过将envir = parent.frame()添加到如下所示的存在检查中来更改fitdist的代码以在您的函数环境中搜索,但我不建议这样做。

if (!exists(ddistname,mode="function",envir=parent.frame()))

但是,由于fitdist调用mledistmledist存在同样的问题,因此仍然无法解决您的问题。

 Error in mledist(data, distname, start, fix.arg, ...) (from #43) :
   The  dsgamma  function must be defined

要采用这种方法,您还必须更改mledist并告诉它在fitdistr的parent.frame中进行搜索。每次加载库时都必须进行这些更改。