2

我已经编辑了我的问题

目标

我只想保留那些成功创建的对象并忽略那些抛出错误的对象。

例子

请注意,这只是一个可重现的示例。我的原始数据集不同。

以下函数采用mtcars数据集的任何变量,拟合三个理论分布,然后返回拟合优度统计数据:

library(fitdistrplus)

fit_distt <- function(var) {
  
v <- mtcars[, var]
  
f1 <- fitdist(data = v, distr = "norm")

f2 <- fitdist(data = v, distr = "nbinom")

f3 <- fitdist(data = v, distr = "gamma")

gofstat(f = list(f1, f2, f3), 
        chisqbreaks = c(0, 3, 3.5, 4, 4.5, 
                        5, 10, 20, 30, 40),
        fitnames = c("normal", "nbinom", "gamma"))

}

例如:

> fit_distt("gear")
Goodness-of-fit statistics
                                normal    nbinom     gamma
Kolmogorov-Smirnov statistic 0.2968616 0.4967268 0.3030232
Cramer-von Mises statistic   0.4944390 1.5117544 0.5153004
Anderson-Darling statistic   3.1060083 7.2858460 3.1742713

Goodness-of-fit criteria
                                 normal   nbinom    gamma
Akaike's Information Criterion 74.33518 109.9331 72.07507
Bayesian Information Criterion 77.26665 112.8646 75.00655

问题

一些理论分布无法成功拟合变量,并fitdist引发错误:

> fit_distt("mpg")
<simpleError in optim(par = vstart, fn = fnobj, fix.arg = fix.arg, obs = data,     gr = gradient, ddistnam = ddistname, hessian = TRUE, method = meth,     lower = lower, upper = upper, ...): function cannot be evaluated at initial parameters>
 Error in fitdist(data = v, distr = "nbinom") : 
  the function mle failed to estimate the parameters, 
                with the error code 100 

此错误发生在f2尝试拟合nbinom连续变量时mpg。但normgamma成功契合。

我想返回gofstat成功拟合的分布并忽略那些抛出错误的分布。

预期产出

即使f2在函数中指定了,如果它抛出错误,我仍然想要以下输出:

> fit_distt("mpg")
Goodness-of-fit statistics
                                 normal      gamma
Kolmogorov-Smirnov statistic 0.12485059 0.08841088
Cramer-von Mises statistic   0.08800019 0.03793323
Anderson-Darling statistic   0.58886727 0.28886166

Goodness-of-fit criteria
                                 normal    gamma
Akaike's Information Criterion 208.7555 205.8416
Bayesian Information Criterion 211.6870 208.7731

我试过的

显然,我可以f2从函数中删除。但这意味着重复每个变量的所有代码。那是很多代码!所以,我还是想用这个功能。

我希望能够将该函数用于任何变量。使用mtcars$mpg时,函数会失败nbinom,但使用mtcars$vs时,函数会失败gamma。在任何情况下,我都想跳过引发错误的拟合并报告gofstat有效的拟合。

我可以用purrr::possibly它悄悄地返回一个合适的结果或抛出错误而不停止在错误上。但我不知道如何仅在gofstat.

4

2 回答 2

2

您可以尝试使用try. 尝试适应分布并仅将其添加到您传递给的列表中(gofstat如果它有效):

library(fitdistrplus)
#> Loading required package: MASS
#> Loading required package: survival


fit_distt <- function(var) {
  
  v <- mtcars[, var]
  
  distributions <- c("norm", "nbinom", "gamma")
  
  fs <- list()
  fitted_distributions <- vector(mode = "character")
  for (i in seq_along(distributions)) {
    # try to fit the model
    fit <- try(fitdist(data = v, distr = distributions[i]), silent = TRUE)    
    
    # if it works, add it to fs. If not, ¯\_(ツ)_/¯
    if (!inherits(fit, "try-error")) {
      fs[[length(fs)+1]] <- fit
      fitted_distributions[length(fitted_distributions)+1] <-  distributions[i]
    }
  }
  
  gofstat(f = fs,
          chisqbreaks = c(0, 3, 3.5, 4, 4.5, 
                          5, 10, 20, 30, 40),
          fitnames = fitted_distributions)
  
}

fit_distt("mpg")
#> <simpleError in optim(par = vstart, fn = fnobj, fix.arg = fix.arg, obs = data,     gr = gradient, ddistnam = ddistname, hessian = TRUE, method = meth,     lower = lower, upper = upper, ...): function cannot be evaluated at initial parameters>
#> Goodness-of-fit statistics
#>                                    norm      gamma
#> Kolmogorov-Smirnov statistic 0.12485059 0.08841088
#> Cramer-von Mises statistic   0.08800019 0.03793323
#> Anderson-Darling statistic   0.58886727 0.28886166
#> 
#> Goodness-of-fit criteria
#>                                    norm    gamma
#> Akaike's Information Criterion 208.7555 205.8416
#> Bayesian Information Criterion 211.6870 208.7731

reprex 包于 2020-10-07 创建(v0.3.0)

于 2020-10-07T17:40:38.600 回答
1

您可以用单个lapply. 如果您让它返回 aNULL而不是 a NA,则该条目将在未列出后消失。因此,以下函数将执行您想要的操作,如此 reprex 所示:

find_mean_of_each_vector_in_a_list <- function(my_list) {
 suppressWarnings(
   as.numeric(
     unlist(
       sapply(my_list,  function(x) if(is.na(mean(x))) NULL else mean(x))
       )))
}

my_list_1 <- list(a = 1:3, b = 5:6, c = 7:10)
my_list_2 <- list(a = 1:3, b = c("a", "b"), c = 7:10)

find_mean_of_each_vector_in_a_list(my_list_1)
#> [1] 2.0 5.5 8.5
find_mean_of_each_vector_in_a_list(my_list_2)
#> [1] 2.0 8.5

reprex 包于 2020-10-07 创建(v0.3.0)

于 2020-10-07T17:00:51.927 回答