R - tryCatch警告消息被写入数据

时间:2014-12-19 11:30:57

标签: r error-handling

我想要实现的目标

我试图写自己的' impute' R中的函数使用tryCatch语句: 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中获取的向量(它们是年龄和标题的向量(例如&#39; Mr&#39;,&#39; Mrs&#39;) impute.values是与impute.var相同类型的向量,但标签取自filter.var(即格式为c('Mr' = 30, 'Mrs' = 25...)

问题

为了检查我的验证是否正常工作,我为该函数提供了一个NAs的命名向量,因此:

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. 我的验证和错误处理策略是否最佳(显然没有错误)?
  3. 非常感谢你的时间。

    罗布

2 个答案:

答案 0 :(得分: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)}
)
}

答案 1 :(得分:0)

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

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

它没有打印&#34; bar&#34;在屏幕上,它将其打印到功能范围,然后返回。返回它的原因是它是打印到函数范围的最后一个值,因此(缺少显式的return()调用)是返回的最佳候选者。

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

  1. 投掷错误;
  2. 不正常处理该错误,而是将其传递到tryCatch的错误处理程序中,并在其中打印;
  3. 因为它是在函数范围内打印的最后一件事,因为由于错误而永远不会命中return()语句,所以将其视为函数的返回值。
  4. 如果你真的想继续处理输入值,即使满足stopifnot()条件,你也不想要一个stopifnot():但是你构造它可能会阻止返回( )从跑步打电话引起怪异。我建议的是在tryCatch之外移动当前在stopifnot()中的条件检查,并将它们粘贴在一系列if()语句中,如果它们不匹配则抛出警告(而不是错误)。在这种情况下,tryCatch并不是必需的。