假设
foo()
每次调用的结果都会发生变化(例如foo
使用PRNG,或从某个服务器下载短暂数据等); foo()
有时会产生警告;和foo()
刚返回的结果将被视为无效。这是一个 玩具 示例:
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
句柄如何返回正确的值。