如何使分布适合R中的样本数据?

Mar*_*tin 5 r curve-fitting

我一直在努力使分布适合我在R中拥有的样本数据。我一直在考虑使用fitdist和fitdistr函数,但是我似乎都遇到了问题。

快速背景;我的代码的输出应该是最合适的分布(从分布列表中)到提供的带有参数的数据。这需要在没有人工干预的情况下发生,因此比较图形不是一种选择。我当时想我可以使每个分布适合数据,从卡方检验中得出p值,然后找到p值最高的分布。我已经在对样本数据进行正态分布方面取得了一些成功,但是当我尝试拟合更复杂的内容(如代码中所示的gamma分布)时,我会遇到各种错误。我究竟做错了什么?

library(fitdistrplus) 
require(MASS) 
set.seed(1) 
testData <- rnorm(1000) 
distlist <- c("norm","unif","exp")

(z <- fitdist(testData,"gamma",start=list(rate=0.1),fix.arg=list(shape=4)))
Run Code Online (Sandbox Code Playgroud)

我得到的错误示例是:

[1]“ optim中的错误(par = vstart,fn = fnobj,fix.arg = fix.arg,obs = data,:\ n'vmmin'中的初始值不是有限的\ n” attr(,“ class”)

fitdist(testData,“ gamma”,start = list(rate = 0.1),fix.arg = list(shape = 4))中的错误:函数mle无法估计参数,错误代码为100

我知道我可能错误地实现了fitdist函数,但是似乎找不到能够适应我的代码目标的简单示例。有人可以帮忙吗?

Tin*_*naW 6

您正在寻找Kolmogorov-Smirnov测试。零假设是数据样本来自假设的分布。

fitData <- function(data, fit="gamma", sample=0.5){
 distrib = list()
 numfit <- length(fit)
 results = matrix(0, ncol=5, nrow=numfit)

 for(i in 1:numfit){
if((fit[i] == "gamma") | 
     (fit[i] == "poisson") | 
     (fit[i] == "weibull") | 
     (fit[i] == "exponential") |
     (fit[i] == "logistic") |
     (fit[i] == "normal") | 
     (fit[i] == "geometric")
) 
  distrib[[i]] = fit[i]
else stop("Provide a valid distribution to fit data" )
 }

 # take a sample of dataset
 n = round(length(data)*sample)
 data = sample(data, size=n, replace=F)

 for(i in 1:numfit) {
  if(distrib[[i]] == "gamma") {
  gf_shape = "gamma"
  fd_g <- fitdistr(data, "gamma")
  est_shape = fd_g$estimate[[1]]
  est_rate = fd_g$estimate[[2]]

  ks = ks.test(data, "pgamma", shape=est_shape, rate=est_rate)

  # add to results
  results[i,] = c(gf_shape, est_shape, est_rate, ks$statistic, ks$p.value)
}

else if(distrib[[i]] == "poisson"){
  gf_shape = "poisson"
  fd_p <- fitdistr(data, "poisson")
  est_lambda = fd_p$estimate[[1]]

  ks = ks.test(data, "ppois", lambda=est_lambda)
  # add to results
  results[i,] = c(gf_shape, est_lambda, "NA", ks$statistic, ks$p.value)
}

else if(distrib[[i]] == "weibull"){
  gf_shape = "weibull"
  fd_w <- fitdistr(data,densfun=dweibull,start=list(scale=1,shape=2))
  est_shape = fd_w$estimate[[1]]
  est_scale = fd_w$estimate[[2]]

  ks = ks.test(data, "pweibull", shape=est_shape, scale=est_scale)
  # add to results
  results[i,] = c(gf_shape, est_shape, est_scale, ks$statistic, ks$p.value) 
}

else if(distrib[[i]] == "normal"){
  gf_shape = "normal"
  fd_n <- fitdistr(data, "normal")
  est_mean = fd_n$estimate[[1]]
  est_sd = fd_n$estimate[[2]]

  ks = ks.test(data, "pnorm", mean=est_mean, sd=est_sd)
  # add to results
  results[i,] = c(gf_shape, est_mean, est_sd, ks$statistic, ks$p.value)
}

else if(distrib[[i]] == "exponential"){
  gf_shape = "exponential"
  fd_e <- fitdistr(data, "exponential")
  est_rate = fd_e$estimate[[1]]
  ks = ks.test(data, "pexp", rate=est_rate)
  # add to results
  results[i,] = c(gf_shape, est_rate, "NA", ks$statistic, ks$p.value)
}

else if(distrib[[i]] == "logistic"){
  gf_shape = "logistic"
  fd_l <- fitdistr(data, "logistic")
  est_location = fd_l$estimate[[1]]
  est_scale = fd_l$estimate[[2]]
  ks = ks.test(data, "plogis", location=est_location, scale=est_scale)
  # add to results
  results[i,] = c(gf_shape, est_location, est_scale, ks$statistic,    ks$p.value) 
    }
  }
  results = rbind(c("distribution", "param1", "param2", "ks stat", "ks    pvalue"),   results)
  #print(results)
  return(results)
  }
Run Code Online (Sandbox Code Playgroud)

应用于您的示例:

library(MASS)
set.seed(1) 
testData <- rnorm(1000) 
res = fitData(testData, fit=c("logistic","normal","exponential","poisson"),
    sample=1)
res
Run Code Online (Sandbox Code Playgroud)

您不会拒绝“正常”的零假设。

参考:http//worldofpiggy.com/2014/02/25/automatic-distribution-fitting-r/