我有一个函数拟合分布并返回一个由分布名称、均值、sd 等组成的向量。我正在测试几个分布但我不能依赖 gofstat() 因为当有太多零要考虑时它会发疯.
因此,我必须手动比较几个变量的 AIC,确定哪些实际上属于“fitdist”类,并返回具有最低 AIC 的变量的名称。一旦我有了它,我计算平均值、标准差等并返回。
目前的代码如下所示:
library(fitdistrplus)
fit_distr <- function(data){
fe <- tryCatch(fitdist(data, "exp"), error = function(e) FALSE )
flogis <- tryCatch(fitdist(data, "logis"), error = function(e) FALSE )
fn <- tryCatch(fitdist(data, "norm"), error = function(e) FALSE)
fp <- tryCatch(fitdist(data, "pois"), error = function(e) FALSE)
fg <- tryCatch(fitdist(data, "gamma"), error = function(e) FALSE)
classFitDist <- c(class(fe), class(flogis), class(fn), class(fp),class(fg))
distributions <- classFitDist == "fitdist"
AIC <- data.frame()
if(class(fe)=="fitdist") {AIC[1,ncol(AIC)+1] <- fe$aic}
if(class(flogis)=="fitdist") {AIC[1,ncol(AIC)+1] <- flogis$aic}
if(class(fn)=="fitdist") {AIC[1,ncol(AIC)+1] <- fn$aic}
if(class(fp)=="fitdist") {AIC[1,ncol(AIC)+1] <- fp$aic}
if(class(fg)=="fitdist") {AIC[1,ncol(AIC)+1] <- fg$aic}
names(AIC) <- c("exp", "logis", "norm", "pois", "gamma")[distributions]
fit <- names(AIC[which.min(AIC)])
mean <- switch (fit,
exp = 1/fe$estimate[[1]],
logis = flogis$estimate[[1]],
norm = fn$estimate[[1]],
pois = fp$estimate[[1]],
gamma = fg$estimate[[1]]/fg$estimate[[2]]
)
sd <- switch (fit,
exp = mean,
logis = (flogis$estimate[[2]]*pi)/sqrt(3),
norm = fn$estimate[[2]],
pois = sqrt(mean),
gamma = sqrt(fg$estimate[[1]]/(fg$estimate[[2]]^2))
)
return(c(fit,mean,sd))
}
它可以工作,但是要考虑数千个样本非常慢。我欢迎任何建议如何优化它并使其“更清洁”和更快。
顺便说一句,这就是我之前所拥有的,但是就像我提到的那样 - 样本包含太多的零,它很合适(双关语无意!)
goodnessoffit <- gofstat(list(fe, flogis, fn, fp, fg)[distributions], fitnames = c("exp", "logis", "norm", "pois","gamma")[distributions])
fit <- names(which(goodnessoffit$aic == min(goodnessoffit$aic)))
ans[!test & ok] <- rep(no, length.out = length(ans))[!test & 中的错误:替换的长度为零