我想定义我自己的分布函数,以便在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指定的函数。我非常感谢你的帮助。
发布于 2014-07-24 16:02:24
问得好。造成此错误的原因是,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’是否在指定的环境中绑定到它的值。如果“”为“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并告诉它在parent.frame of fitdistr中搜索。每次加载库时,都必须进行这些更改。
https://stackoverflow.com/questions/24934716
复制相似问题