R:函数的意外行为(可能是由于函数中公式对象的环境范围)

R: unexpected behaviour of function (probably due to environmental scope of formula object within function)

提问人:Fabou 提问时间:6/15/2023 更新时间:6/15/2023 访问量:61

问:

虽然是 R 的长期用户,但我几乎没有用 R 编写复杂程序的经验。在我的第一次尝试中,我遇到了代码的意外行为。也就是说,如果我尝试运行一个我已经定义了自己的函数,一个围绕 gamlss 回归模型适配的包装器,该函数就会失败。逐行交互地运行函数中的代码就可以了。奇怪的是,一旦我以交互方式运行代码一次,该函数就会显示预期的行为。

这里有一个最小的可重现的例子:

首先,我加载所需的包

    library(data.table)
    library(gamlss)

我定义了我的包装器函数

    fun.wrapper <- function(dt, cores){
      all_vars <- colnames(dt)[colnames(dt) > "b"]
      scope_vars <- all_vars[1:ceiling(length(all_vars)/2)]
      formula_full <- as.formula(paste0("a ~ ", paste(all_vars, collapse = " + ")))
      mod0 <- gamlss(formula = formula_full, data = dt, family = "NO", trace = FALSE)
      droper <- drop1All(object = mod0, scope = scope_vars, print = FALSE, parallel = ifelse(cores>1, "multicore", "no"), ncpus = cores)
      return(droper)
    }

我初始化一个随机数据集

    data <- data.table(
      x = rbinom(size = 1, prob = 0.3, n = 10),
      y = rbinom(size = 1, prob = 0.1, n = 10),
      z = rbinom(size = 1, prob = 0.2, n = 10),
      a = rnorm(n = 10)^2)

我将该函数应用于数据,但失败并出现错误

    res_f1 <- fun.wrapper(dt = data, cores = 1)

如果我一行一行地从包装器运行代码,结果符合预期

    dt <- data
    cores <- 1
    all_vars <- colnames(dt)[colnames(dt) > "b"]
    scope_vars <- all_vars[1:ceiling(length(all_vars)/2)]
    formula_full <- as.formula(paste0("a ~ ", paste(all_vars, collapse = " + ")))
    mod0 <- gamlss(formula_full, data = dt, family = "NO", trace = FALSE)
    res_i1 <- drop1All(object = mod0, scope = scope_vars, print = FALSE, parallel = ifelse(cores>1, "multicore", "no"), ncpus = cores)

完成此操作后,我也可以成功运行包装器函数

   res_f2 <- fun.wrapper(dt = data, cores = 1)

我尝试了几次,主要是反复试验和错误驱动的尝试来解决这个问题。我阅读了有关词法范围和闭包的文章,因为我强烈假设上面的 drop1All 调用访问了错误的数据。我试图将各自的变量分配给全局环境并<<。这些都没有奏效。

因此,如果你们中的一个人能为我指出这个问题的解决方案,我将非常高兴。提前致谢。

sessionInfo()
R version 4.2.1 (2022-06-23)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 20.04.4 LTS

Matrix products: default
BLAS:   /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.9.0
LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.9.0

locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
 [3] LC_TIME=de_AT.UTF-8        LC_COLLATE=en_US.UTF-8    
 [5] LC_MONETARY=de_AT.UTF-8    LC_MESSAGES=en_US.UTF-8   
 [7] LC_PAPER=de_AT.UTF-8       LC_NAME=C                 
 [9] LC_ADDRESS=C               LC_TELEPHONE=C            
[11] LC_MEASUREMENT=de_AT.UTF-8 LC_IDENTIFICATION=C       

attached base packages:
[1] parallel  splines   stats     graphics  grDevices utils     datasets 
[8] methods   base     

other attached packages:
[1] gamlss_5.4-12     nlme_3.1-162      gamlss.dist_6.0-5 MASS_7.3-58      
[5] gamlss.data_6.0-2 data.table_1.14.8

loaded via a namespace (and not attached):
[1] compiler_4.2.1  Matrix_1.5-3    survival_3.5-5  grid_4.2.1     
[5] lattice_0.20-45

R 函数式编程 闭包 词法范围 gamlss

评论

2赞 SmokeyShakers 6/15/2023
错误消息是什么?
0赞 Fabou 6/15/2023
@SmokeyShakes感谢您的跟进。以下是首次执行期间生成的错误消息: 项为 x 的模型失败 项为 y 的模型失败 警告消息: 1:在 is.na(数据):is.na() 应用于类型为“closure”的非(列表或向量) 2:在 is.na(data) 中:应用于类型为“closure”的非(列表或向量)的 is.na()

答: 暂无答案