我想定义自己的分布函数,用于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指定的函数。我非常感谢你的帮助。
答案 0 :(得分:3)
好问题。出现此错误的原因是fitdistrplus
包的作者使用exists()
来检查函数所需参数的变体。
以下是fitdist
和mledist
函数代码的摘录。作者采用distr
给出的值,并在全球环境和定义fitdist
和mledist
的环境中搜索适当的密度和概率函数。
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
调用mledist
和mledist
存在同样的问题,因此仍然无法解决您的问题。
Error in mledist(data, distname, start, fix.arg, ...) (from #43) :
The dsgamma function must be defined
要采用这种方法,您还必须更改mledist
并告诉它在fitdistr
的parent.frame中进行搜索。每次加载库时都必须进行这些更改。