有没有办法在R中使用tryCatch(或类似)作为循环,或者在warning参数中操纵expr?
我有一个回归模型(有没有办法在R中使用tryCatch(或类似)作为循环,或者在warning参数中操纵expr?,r,exception,try-catch,warnings,R,Exception,Try Catch,Warnings,我有一个回归模型(lm或glm或lmer…),我有fitmodel也许您可以在处理条件下再次分配x tryCatch( warning = function(cnd) { x <- suppressWarnings(as.numeric(y)) print(x)}, expr = {x <- as.numeric(y)} ) #> [1] NA tryCatch( 警告=功能(cnd){ x不要把作业放在tryCatch调用中,把它放在外部。例如 y
lm
或glm
或lmer
…),我有fitmodel也许您可以在处理条件下再次分配x
tryCatch(
warning = function(cnd) {
x <- suppressWarnings(as.numeric(y))
print(x)},
expr = {x <- as.numeric(y)}
)
#> [1] NA
tryCatch(
警告=功能(cnd){
x不要把作业放在tryCatch
调用中,把它放在外部。例如
y <- "a"
x <- tryCatch(expr = {as.numeric(y)},
warning = function(w) {y})
y <- "a"
res <- evaluate::evaluate(quote(x <- as.numeric(y)))
for (i in seq_along(res)) {
if (inherits(res[[i]], "warning") &&
conditionMessage(res[[i]]) == gettext("NAs introduced by coercion",
domain = "R"))
x <- y
}
编辑以添加:
要允许评估在处理警告之前继续完成,您不能使用tryCatch
。evaluate
包有一个函数(也称为evaluate
)可以完成此操作。例如
y <- "a"
x <- tryCatch(expr = {as.numeric(y)},
warning = function(w) {y})
y <- "a"
res <- evaluate::evaluate(quote(x <- as.numeric(y)))
for (i in seq_along(res)) {
if (inherits(res[[i]], "warning") &&
conditionMessage(res[[i]]) == gettext("NAs introduced by coercion",
domain = "R"))
x <- y
}
<代码> y> p>你在寻找类似的东西吗?如果它是用<代码> y运行的,看起来你在寻找一个函数包,它既能捕获函数调用的返回值又能捕捉到副作用。我想Purr::悄悄地< /代码>是这类任务的完美候选。
quietly <- purrr::quietly
foo <- function(x) {
if (x < 3)
warning(x, " is less than 3")
if (x < 4)
warning(x, " is less than 4")
x
}
update_foo <- function(x, y) {
x <- x + y
foo(x)
}
keep_doing <- function(inputs) {
out <- quietly(foo)(inputs)
repeat {
if (length(out$warnings) < 1L)
return(out$result)
cat(paste0(out$warnings, collapse = ", "), "\n")
# This is for you to see the process. You can delete this line.
if (grepl("less than 3", out$warnings[[1L]])) {
out <- quietly(update_foo)(out$result, 1.5)
} else if (grepl("less than 4", out$warnings[[1L]])) {
out <- quietly(update_foo)(out$result, 1)
}
}
}
从根本上说,问题在于处理程序是在赋值发生之前调用的。即使不是这样,处理程序运行在与tryCatch
表达式不同的作用域中,因此处理程序无法访问另一个作用域中的名称
我们需要将处理与值转换分开
对于错误(但不是警告),base R提供函数try
,该函数包装tryCatch
,以实现此效果。但是,不鼓励使用try
,因为它的返回类型是.1,如上所述,'purr'提供正确键入(例如安全地
)以实现类似效果
但是,我们也可以建立自己的,这可能更适合这种情况:
with_warning = function (expr) {
self = environment()
warning = NULL
result = withCallingHandlers(expr, warning = function (w) {
self$warning = w
tryInvokeRestart('muffleWarning')
})
list(result = result, warning = warning)
}
这为我们提供了一个包装器,用于区分结果值和警告。我们现在可以使用它来实现您的需求:
fitmodel = with(with_warning(lm(inputs)), {
if (! is.null(warning)) {
if (conditionMessage(warning) satisfies something) {
update(result, something suitable to do on the model)
} else {
update(result, something2 suitable to do on the model)
}
} else {
result
}
})
1这意味着try
的返回类型不区分类型为try error
的错误值和非错误值。这是一种可能发生的实际情况,例如,当嵌套多个try
调用时。我将赋值放在tryCatch
中,因为我想稍后在内部使用warning
参数,我询问是否有可能。我认为除了像我的回答中那样复制计算之外,使用基本R代码是不可能的。R代码可以访问警告消息或表达式值,但不能同时访问两者。但是,evaluate::evaluate()
函数可以做到这一点;我将添加一个示例。
with_warning = function (expr) {
self = environment()
warning = NULL
result = withCallingHandlers(expr, warning = function (w) {
self$warning = w
tryInvokeRestart('muffleWarning')
})
list(result = result, warning = warning)
}
fitmodel = with(with_warning(lm(inputs)), {
if (! is.null(warning)) {
if (conditionMessage(warning) satisfies something) {
update(result, something suitable to do on the model)
} else {
update(result, something2 suitable to do on the model)
}
} else {
result
}
})