Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/84.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
检查在R脚本中使用随机数生成器的函数的综合方法?_R_Random_Random Seed - Fatal编程技术网

检查在R脚本中使用随机数生成器的函数的综合方法?

检查在R脚本中使用随机数生成器的函数的综合方法?,r,random,random-seed,R,Random,Random Seed,是否有一种智能的方法来识别在R脚本的任意点使用.Random.seed(R中的随机数生成器状态)的所有函数 用例:我们有一个不断变化的数据集,记录[行]和信息[列]——我们经常添加新记录,但我们也更新某些列中的信息。因此,数据集不断变化。我们用插补来填充一些缺失的数据,这需要使用sample()函数生成随机数。因此,每当我们添加新行或更新列中的任何信息时,随机输入的数字都会发生变化——这是意料之中的。我们在每次随机插补开始时使用set.seed(),因此,如果一列发生变化,但零行发生变化,则其他

是否有一种智能的方法来识别在R脚本的任意点使用
.Random.seed
(R中的随机数生成器状态)的所有函数

用例:我们有一个不断变化的数据集,记录[行]和信息[列]——我们经常添加新记录,但我们也更新某些列中的信息。因此,数据集不断变化。我们用插补来填充一些缺失的数据,这需要使用
sample()
函数生成随机数。因此,每当我们添加新行或更新列中的任何信息时,随机输入的数字都会发生变化——这是意料之中的。我们在每次随机插补开始时使用
set.seed()
,因此,如果一列发生变化,但零行发生变化,则其他随机生成的列不会受到影响

我的印象是,在我们整个代码库中,唯一接触过随机种子的函数是
sample()
函数,但我想以某种方式验证一下

编辑:即使是在碰到随机数状态时打印函数调用的东西也会有帮助,就像触发调试过的函数时
debug()
一样?出于我们的目的,可以非常安全地假设,如果我们运行一次脚本进行动态计算,并且没有触发其他随机函数,那么我们是安全的


谢谢

尽管有我的评论,这里还是有一个蛮力的方法来检查这一点:

rm(.Random.seed) # if it already exists
makeActiveBinding('.Random.seed',
                  function () stop('Something touched my seed', call. = FALSE),
                  globalenv())
这将使
.Random.seed
成为一个在触摸时抛出错误的对象

这是可行的,但破坏性很大。这里有一个更温和的变体。它有几个有趣的特性:

  • 它允许启用和禁用调试
    .Random.seed
  • 它支持获取和设置种子
  • 它记录调用,但不停止执行
  • 它维护一个不应该被记录的顶级呼叫的“白名单”
使用此选项,您可以编写以下代码,例如:

# Ignore calls coming from sample.int
> debug_random_seed(ignore = sample.int)

> sample(5)
Getting .Random.seed
Called from sample(5)
Setting .Random.seed
Called from sample(5)
[1] 3 5 4 1 2

> sample.int(5)
[1] 5 1 2 4 3

> undebug_random_seed()

> sample(5)
[1] 2 1 5 3 4
以下是实施的全部荣耀:

debug_random_seed = local({
    function (ignore) {
        seed_scope = parent.env(environment())

        if (is.function(ignore)) ignore = list(ignore)

        if (exists('.Random.seed', globalenv())) {
            if (bindingIsActive('.Random.seed', globalenv())) {
                warning('.Random.seed is already being debugged')
                return(invisible())
            }
        } else {
            set.seed(NULL)
        }

        # Save existing seed before deleting
        assign('random_seed', .Random.seed, seed_scope)
        rm(.Random.seed, envir = globalenv())

        debug_seed = function (new_value) {
            if (sys.nframe() > 1 &&
                ! any(vapply(ignore, identical, logical(1), sys.function(1)))
            ) {
                if (missing(new_value)) {
                    message('Getting .Random.seed')
                } else {
                    message('Setting .Random.seed')
                }
                message('Called from ', deparse(sys.call(1)))
            }

            if (! missing(new_value)) {
                assign('random_seed', new_value, seed_scope)
            }

            random_seed
        }

        makeActiveBinding('.Random.seed', debug_seed, globalenv())
    }
})

undebug_random_seed = function () {
    if (! (exists('.Random.seed', globalenv()) &&
           bindingIsActive('.Random.seed', globalenv()))) {
        warning('.Random.seed is not being debugged')
        return(invisible())
    }

    seed = suppressMessages(.Random.seed)
    rm('.Random.seed', envir = globalenv())
    assign('.Random.seed', seed, globalenv())
}
关于代码的一些注释:

  • debug\u random\u seed
    函数是在它自己的私有环境中定义的。此环境由代码中的
    seed\u scope
    指定。这样可以防止将私有
    随机_seed
    变量泄漏到全局环境中
  • 该函数会防御性地检查是否已启用调试。也许是杀伤力太大了
  • 只有在函数调用中访问种子时,才会打印调试信息。如果用户直接在R控制台上检查
    .Random.seed
    ,则不会发生日志记录

我不得不猜测,否决你的懒惰者认为你可以进一步简化你的问题。不幸的是,在没有给出原因的情况下,仍然有可能否决一个问题。祝你好运不,根本没有办法。因为R是动态计算的,所以不能编写静态分析器来全面检查这一点。试探法可能会让你接近,但为此构建一个是相当困难的。我得说你运气不好。如果你想确保任何东西都不接触你的随机数生成器的状态,不要依赖R,写一个小的C++函数,它使用基于<代码> <代码>标准头的生成器,并在R.R.KoRADRoOLPHP中导入那个函数。但我能想到的唯一一件事是在整个脚本中检查
.Random.seed
(将结果保存在矩阵或其他东西中),并查找它何时更改。至于代码扫描器/函数检查器,我同意康拉德的观点,这可能是不可能的。太容易想出病态的例子了。@AnthonyDamico:我注意到你花了大部分的时间来回答问题。如果你需要一个问题来“慷慨”,我很乐意用我的一些代表来补充你的问题。我怀疑你知道我的“真名”。这几乎是完美的。有没有办法让
function()stop()
忽略
sample()
函数?我认为像
if(!any(unlist(lappy(c)(“sample”,“runif”),function(w)grepl(w,paste(as.character(sys.calls()),collapse=“))))这样丑陋的解决方案可以跳过这两个函数,但可能有一个更干净的方法approach@AnthonyDamico它在紧要关头起作用。我更喜欢比较实际的通话符号,而不是类似的字符串,但不幸的是,我现在在手机上,所以我不能写一个例子。@AnthonyDamico显然我没有更好的事情要做。;-)检查答案中的新代码。这应该满足你的每一个梦想。