关于 set.seed() 的 R 包提交错误
R package submission error concerning set.seed()
我最近向 CRAN 提交了一个包,该包通过了所有自动检查,但未能通过手动检查。其中一个错误如下:
Please do not set a seed to a specific number within a function.
Please do not modifiy the .GlobalEnv. This is not allowed by the CRAN policies.
我相信这些评论所指的代码行如下
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”,因为它们的维数是函数的输入,因此会因调查人员的偏好而异。
修复种子后,如果用户使用相同的参数尝试此代码,则每次都会获得相同的结果。
假设这段代码位于仅与模拟相关的更大块中,只需删除 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)
}
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 的问题,因为它似乎在做与您被告知不要做的事情相同的事情 - 不同之处可能在于您的版本可能会覆盖现有种子,而该代码检查种子是否已存在。
如果您真的非常想在函数中设置种子,我相信您和任何人都不应该这样做,请保存当前种子,做任何您想做的事,然后在退出函数之前将其重置为保存的值.
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)
我最近向 CRAN 提交了一个包,该包通过了所有自动检查,但未能通过手动检查。其中一个错误如下:
Please do not set a seed to a specific number within a function.
Please do not modifiy the .GlobalEnv. This is not allowed by the CRAN policies.
我相信这些评论所指的代码行如下
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”,因为它们的维数是函数的输入,因此会因调查人员的偏好而异。
修复种子后,如果用户使用相同的参数尝试此代码,则每次都会获得相同的结果。
假设这段代码位于仅与模拟相关的更大块中,只需删除 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)
}
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 的问题,因为它似乎在做与您被告知不要做的事情相同的事情 - 不同之处可能在于您的版本可能会覆盖现有种子,而该代码检查种子是否已存在。
如果您真的非常想在函数中设置种子,我相信您和任何人都不应该这样做,请保存当前种子,做任何您想做的事,然后在退出函数之前将其重置为保存的值.
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)