如何重复(或递归)直到没有警告?

时间:2017-05-27 21:59:17

标签: r warnings

假设

  1. foo()每次调用的结果都会发生变化(例如foo使用PRNG,或从某个服务器下载短暂数据等);
  2. 评估foo() 有时会产生警告;和
  3. 某些(并非所有!)这些警告都是"严重",这意味着foo()刚返回的结果将被视为无效。
  4. 这是一个 玩具 示例:

    foo <- function () {
        n = 10
    
        fake.data <- list(x = rnorm(n, mean = 0, sd = 1),
                          y = rbinom(n, size = 1, prob = 0.3))
    
        model <- glm(formula = y ~ x,
                     family = binomial(link = "logit"),
                     data = fake.data)
    
        coef(model)[[2]]
    }
    

    所以,

    set.seed(10); foo()
    ## [1] -1.369938
    
    set.seed(2); foo()
    ## [1] 52.89538
    ## Warning message:
    ## glm.fit: fitted probabilities numerically 0 or 1 occurred
    
    set.seed(23); foo()
    ## [1] 1673.609
    ## Warning messages:
    ## 1: glm.fit: algorithm did not converge
    ## 2: glm.fit: fitted probabilities numerically 0 or 1 occurred
    
    foo()
    ## [1] 0.5127775
    

    在上面的示例输出中显示的两种类型的警告中,如果只有foo,请说明

    的形式

    glm.fit: algorithm did not converge
    

    应被视为&#34;认真的&#34; (如上文(3)中所定义)。

    现在,我想定义一个函数bar,它返回第一个foo()调用的结果,其中没有&#34;严重的&#34;警告。

    另外,为了帮助进行此演示,我将定义以下辅助函数来设置PRNG的种子(用于再现性)并立即调用bar

    baz <- function (seed) {
        set.seed(seed)
        bar()
    }
    

    如果baz已定义,如果bar按预期工作,则表达式c(baz(10), baz(23), baz(2))应评估为

    [1] -1.3699380  0.5127775 52.8953800
    

    特别是,此向量中的第二个值(对应于baz(23))应该等于将种子设置为23后第二次调用foo()的结果第一次这样的电话会产生一个严重的警告。

    我对bar的第一个想法 1 是:

    bar <- function () {
    
        result <- foo()
    
        if (!is.null(warnings()) &&
            "glm.fit: algorithm did not converge" %in% names(last.warning)) {
            cat("doing over\n")
            return (bar())
        }
    
        result
    }
    

    这不起作用。例如,

    c(baz(10), baz(23), baz(2))
    ## [1]   -1.369938 1673.608858   52.895383
    

    请注意baz(23)的值为1673.608858,而非0.5127775。

    此外,如果我现在再次评估baz(10),不仅我没有得到预期的结果,-1.369938,但实际上我没有得到结果,因为调用进入无限递归。 / p>

    这表明先前执行last.warning的{​​{1}}仍然存在。

    所以我尝试了这个:

    foo

    这避免了无限递归,但bar <- function () { assign("last.warning", NULL, envir = baseenv()) result <- foo() if (!is.null(warnings()) && "glm.fit: algorithm did not converge" %in% names(last.warning)) { cat("doing over\n") return (bar()) } result } 仍然产生(错误的)结果,1673.608858。

    Q1:如何撰写baz(23)以便bar返回0.5127775,baz(23)永远不会进入无限递归?

    Q2:有没有办法阻止向终端打印警告而不会失去baz检测到严重&#34;的能力。执行bar期间的警告?

    1 AFAICT,foo()在这里不起作用,因为只要有任何句柄,tryCatch句柄就会导致递归调用所有的警告,是否严重&#34;或不。当发生唯一的非严重警告时,我不知道warning句柄如何返回正确的值。

0 个答案:

没有答案