2014-12-19 4 views
0

То, что я пытаюсь достичьR - tryCatch предупреждение записываются данные

Я пытаюсь написать свою собственную функцию «вменить» в 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.var и filter.var векторы взяты из data.frame (они являются векторами века и названия (например, «мистер», «миссис») impute.values является вектором того же типа, как impute.var но с этикетками взяты из filter.var (т.е. имеет вид c('Mr' = 30, 'Mrs' = 25...))

проблема

Чтобы проверить, если моя проверка работала я снабжал функцию с именем VEC тор НАН Украины, таким образом:

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. Является ли моя стратегия проверки и обработки ошибок оптимальной (очевидно, без ошибок)?

Большое спасибо за ваше время.

Rob

ответ

0

Это по существу две разные проблемы. Первая проблема заключается в том, что инструкции печати внутри функции не печатаются на терминале, они печатаются в области действия функции. Например:

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

Он не распечатывал «бар» на экране, он печатал его в области функций, а затем возвращал. Причина, по которой она вернулась, заключалась в том, что это последнее значение было напечатано в области видимости функции, и поэтому (отсутствие явного вызова return()) является лучшим кандидатом для возврата.

Итак, ваш код (в последовательности):

  1. Бросив ошибку;
  2. Не обрабатывать эту ошибку нормально, а вместо этого передавать ее в обработчик ошибок tryCatch, где он печатается;
  3. Потому что это последнее, что напечатано в пределах области функции, так как оператор return() никогда не попадает из-за ошибки, рассматривая его как возвращаемое значение из функции.

Если вы действительно хотите продолжить обработку входных значений, даже если условия stopifnot() выполнены, вам не нужна функция stopifnot(): однако вы структурируете, что это может предотвратить вызов return() бегать и вызывать странность. То, что я предлагаю, вместо этого перемещает условные проверки в настоящее время в stopifnot() вне tryCatch и вставляет их в ряд операторов if(), которые выдают предупреждения (а не ошибки), если они не совпадают. tryCatch на самом деле не нужна в этой ситуации.

+0

Спасибо за Ваш ответ и информацию о печати. Я этого не осознавал. Что мне нужно, это две разные вещи: 1. Если 'stopifnot' выходит из строя, функция останавливается с сообщением об ошибке. 2. Если функция запускается, но оставляет некоторые значения не вмененными, возникает предупреждение. Т.е. я не хочу, чтобы функция продолжалась, если 'stopifnots' терпит неудачу. –

+0

Хорошо! Помогает ли ответ? Если нет: какие две разные вещи? –

+0

К сожалению, я продолжаю нажимать клавишу ввода, прежде чем заканчивать комментарий. –

1

Спасибо Oliver.

Рабочий код теперь:

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)} 
) 
} 
Смежные вопросы