【问题标题】:R - tryCatch warning message being written to dataR - 正在写入数据的 tryCatch 警告消息
【发布时间】:2014-12-19 20:42:50
【问题描述】:

我正在努力实现的目标

我正在尝试使用 tryCatch 语句在 R 中编写我自己的“估算”函数: 1. 输出包含函数名称的警告/错误消息,以便我可以更轻松地调试。 2. 如果函数运行正常但未估算所有缺失值,则发出警告。

ImputeVariables <- function(impute.var, impute.values, 
                        filter.var){
# function to impute values. 
# impute.var = variables with NAs
# impute.values = the missing value(s) to replace NAs, value labesl are levels
# filter.var = the variables to filter on. 
# filter.levels = the categories of filter.var
tryCatch({
    filter.levels <- names(impute.values)
    # Validation
    stopifnot(class(impute.var) == class(impute.values), 
             length(impute.values) > 0,
             sum(is.na(impute.values)) == 0)
    # Impute values
    for(level in filter.levels){
        impute.var[which(filter.var == level & is.na(impute.var))] <- 
            impute.values[level]
    }
    # Check if all NAs removed.  Throw warning if not. 
    if(sum(is.na(impute.var)) > 0){
        warning("Not all NAs removed")
    }
    # Return values
    return(impute.var)

}, 
    error = function(err) print(paste0("ImputeValues: ",err)),
    warning = function(war) print(paste0("ImputeValues: ",war))
)
}

impute.varfilter.var 是取自 data.frame 的向量(它们是年龄和头衔的向量(例如“先生”、“夫人”) impute.values 是与 impute.var 相同类型的向量,但其标签取自 filter.var(即格式为 c('Mr' = 30, 'Mrs' = 25...)

问题

为了检查我的验证是否有效,我为函数提供了一个命名的 NA 向量,因此:

ages <-   c(34, 22, NA, 17, 38, NA)
titles <- c("Mr", "Mr", "Mr", "Mrs", "Mrs", "Mrs")
ages.values <- c("Mr" = NA, "Mrs" = NA)

ages.new <- ImputeVariables(ages, ages.values, titles)

print(ages.new)

但它会输出以下内容:

 "ImputeValues: Error: class(impute.var) == class(impute.values) is not TRUE\n"
 "ImputeValues: Error: class(impute.var) == class(impute.values) is not TRUE\n"

这两行是由于打印ages.new向量的函数和下面的打印语句打印ages.new(为什么?)

如果我注释掉验证(stopifnot 函数),那么我会得到:

"ImputeValues: simpleWarning in doTryCatch(return(expr), name, parentenv, handler): Not all NAs removed\n" 

我在问什么

  1. 为什么 tryCatch 块会这样?
  2. 我的验证和错误处理策略是否最佳(显然没有错误)?

非常感谢您的宝贵时间。

罗伯

【问题讨论】:

    标签: r error-handling


    【解决方案1】:

    谢谢奥利弗。

    现在的工作代码是:

     ImputeVariables <- function(impute.var, impute.values, 
                            filter.var){
    # function to impute values. 
    # impute.var = variables with NAs
    # impute.values = the missing value(s) to replace NAs, value labesl are levels
    # filter.var = the variables to filter on. 
    # filter.levels = the categories of filter.var
    tryCatch({
        filter.levels <- names(impute.values)
        # Validation
        stopifnot(class(impute.var) == class(impute.values), 
                 length(impute.values) > 0,
                 sum(is.na(impute.values)) == 0)
        # Impute values
        for(level in filter.levels){
            impute.var[which(filter.var == level & is.na(impute.var))] <- 
                impute.values[level]
        }
        # Check if all NAs removed.  Throw warning if not. 
        if(sum(is.na(impute.var)) > 0){
            warning("Not all NAs removed")
        }
        # Return values
        return(impute.var)
    
    }, 
        error = function(err) stop(paste0("ImputeValues: ",err)),
        warning = function(war) {
            message(paste0("ImputeValues: ",war))
            return(impute.var)}
    )
    }
    

    【讨论】:

      【解决方案2】:

      这本质上是两个不同的问题。第一个问题是函数内的打印语句不会打印到终端,而是打印到函数的范围。举个例子:

      > foo <- function(){
           print("bar")
        }
      > foo()
      [1] "bar"
      

      它没有将“bar”打印到您的屏幕上,而是将其打印到函数范围然后返回它。它返回它的原因是它是打印到函数作用域的最后一个值,因此(缺少显式的 return() 调用)是返回的最佳候选。

      所以,您的代码是(按顺序):

      1. 抛出错误;
      2. 不正常处理该错误,而是将其传递给 tryCatch 的错误处理程序,并在其中打印;
      3. 因为它是函数范围内最后打印的东西,因为 return() 语句永远不会因为错误而被命中,将其视为函数的返回值。

      如果您真的想在满足 stopifnot() 条件的情况下继续处理输入值,则不需要 stopifnot():但是您构造它可能会阻止 return() 调用运行并导致怪异。我的建议是将当前在 stopifnot() 中的条件检查移到 tryCatch 之外,并将它们粘贴在一系列 if() 语句中,如果它们不匹配,则会抛出警告(而不是错误)。在这种情况下,tryCatch 并不是真正必要的。

      【讨论】:

      • 感谢您的回复以及有关打印的信息。我没有意识到这一点。我想要的是两件不同的事情: 1. 如果stopifnot 失败,则函数会停止并显示错误消息。 2. 如果函数运行但留下一些未估算的值,则会产生警告。即,如果stopifnots 失败,我不希望该功能继续。
      • 好的!答案有帮助吗?如果不是:哪两个不同的东西?
      • 对不起,我在完成评论之前一直按回车。
      • 明白了。那么,为什么要使用 tryCatch 呢?如果 stopifnot 失败,它将停止并显示错误消息。如果不是所有的 NA 都被删除,它会抛出一个警告。如果 tryCatch 的目的是控制错误消息的内容,那么请将您的第一个 print() 替换为 error(),将第二个 print() 替换为 warning()。
      • 感谢您的帮助。你已经解释了一切。
      猜你喜欢
      • 2022-08-20
      • 2016-06-17
      • 2018-02-24
      • 2023-04-07
      • 1970-01-01
      • 2019-12-31
      • 2014-05-31
      • 2012-02-09
      • 2017-10-13
      相关资源
      最近更新 更多