【问题标题】:R package submission error concerning set.seed()关于 set.seed() 的 R 包提交错误
【发布时间】:2022-01-08 02:32:55
【问题描述】:

我最近向 CRAN 提交了一个包,它通过了所有自动检查,但未能通过手动检查。错误之一如下:

请不要将种子设置为函数中的特定数字。

请不要修改 .GlobalEnv。 CRAN 政策不允许这样做。

我相信这些 cmets 所指的代码行如下

    if(simul == TRUE){

        set.seed(42)

    }

    w <- matrix(data = rbinom(n = p, size = 1, prob = 0.5), ncol = 1)

    beta <- w*beta-(1-w)*beta

    s <- round((1-sparsity)*p)                  

    toReplace <- sample(p, size = s)

    beta <- replace(beta, list = toReplace, values = 0)


    # Generate the random p-columned matrix of indicator series. 

    X <- matrix(data = rnorm ((n_l*m) * p, mean = mean_X, sd = sd_X), ncol = p, nrow = n_l*m)


    if(simul == TRUE){

        rm(.Random.seed, envir = globalenv())

    }

本质上,我允许该函数包含一个模拟选项“simul”,这样当设置为“TRUE”时,矩阵“X”和系数向量“beta”保持固定。我删除了该段末尾的种子(最后几行),因为其余代码包含应在每次模拟迭代时更改的变量。但是,正如 CRAN 的反馈中所述,这是不允许的。有什么替代方法可以解决这个问题?当“simul”为“TRUE”时,我无法设置固定向量“beta”或矩阵“X”,因为这些维度是函数的输入,因此会根据调查人员的偏好而有所不同。

【问题讨论】:

  • 你应该让用户设置种子,这就是 CRAN 不喜欢这种做法的原因。
  • 如果你把这个种子作为你的函数的一个参数,这样函数的用户可以随意设置任何整数呢?
  • 同上,只是让用户设置种子,这样每次都能得到相同的结果。至于改变全球环境,为什么要这么做?无论如何,如果您让 seed 作为参数传递,您就不需要“清理”环境。

标签: r r-package


【解决方案1】:

如果你真的,真的,想在一个函数中设置种子,我相信你和任何人都应该这样做,保存当前种子,做你想做的任何事情,然后在退出函数之前将其重置为保存的值。

old_seed <- .Random.seed
rnorm(1)
#[1] -1.173346

set.seed(42)
rbinom(1, size = 1, prob = 0.5)
#[1] 0

.Random.seed <- old_seed
rnorm(1)
#[1] -1.173346

在没有message 指令的函数中,它可能类似于以下内容。请注意,该函数不打印任何内容,它从不调用任何伪 RNG,并且始终输出 TRUE。重点是保存种子的当前值并在on.exit中重置种子。

f <- function(simul = FALSE){
  if(simul){
    message("simul is TRUE")
    old_seed <- .Random.seed
    on.exit(.Random.seed <- old_seed)
    # rest of code
  } else message("simul is FALSE")
  invisible(TRUE)
}

f()
s <- .Random.seed
f(TRUE)
identical(s, .Random.seed)
#[1] TRUE

rm(s)

【讨论】:

    【解决方案2】:

    Bio devel 邮件列表中提出了类似的问题。那里的建议是使用withr::with_seed 的功能。您的代码可能会变成:

    library(withr)
    
    if(simul == TRUE){
      w <- with_seed(42, matrix(data = rbinom(n = p, size = 1, prob = 0.5), ncol = 1))
    } else {
      w <- matrix(data = rbinom(n = p, size = 1, prob = 0.5), ncol = 1)
      
    } 
    
    
    beta <- w*beta-(1-w)*beta
    
    s <- round((1-sparsity)*p)                  
    
    toReplace <- sample(p, size = s)
    
    beta <- replace(beta, list = toReplace, values = 0)
    
    
    # Generate the random p-columned matrix of indicator series. 
    
    X <- matrix(data = rnorm ((n_l*m) * p, mean = mean_X, sd = sd_X), ncol = p, nrow = n_l*m)
    

    当然,这引发了withr 是如何加入 CRAN 的问题,因为它似乎做了与您被告知不要做的事情相同的事情 - 不同之处可能在于您的版本可能会覆盖现有种子,而该代码检查种子是否已经存在。

    【讨论】:

      【解决方案3】:

      当你修复种子时,如果用户用相同的参数尝试这段代码,每次都会得到相同的结果。

      假设这段代码在一个更大的块中,只与模拟相关,只需去掉setseed() 并尝试类似的操作:

      if(simul == TRUE){
          w <- matrix(data = rbinom(n = p, size = 1, prob = 0.5), ncol = 1)
          beta <- w*beta-(1-w)*beta
          s <- round((1-sparsity)*p)                  
          toReplace <- sample(p, size = s)
          beta <- replace(beta, list = toReplace, values = 0)
      
          # Generate the random p-columned matrix of indicator series. 
          X <- matrix(data = rnorm ((n_l*m) * p, mean = mean_X, sd = sd_X), ncol = p, nrow = n_l*m)
      }
      

      【讨论】:

        猜你喜欢
        • 2012-06-10
        • 2014-10-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-02-24
        • 1970-01-01
        • 2023-01-07
        • 1970-01-01
        相关资源
        最近更新 更多