Это тоже работает.Это немного более кратко / эффективно.Я могу проверить с microbenchmark
позже, но похоже, что ваша проблема уже решена.
dt <- data.frame(a_check=c(20,2,1,NA,0),
b_check=c(0,1,NA,1,15))
valid_values <- list(a_check= c(1,2,3), b_check= c(0,1))
dt_errors <- sapply(1:ncol(dt), function(x) ifelse(!dt[[x]] %in% valid_values[[x]],
paste0(toupper(names(dt)[x]),
" must be one of the following values: ",
paste(valid_values[[x]], collapse = ", ")),
""))
dt$error <- apply(dt_errors, 1 , paste, collapse = " & ")
dt$error <- trimws(gsub("^ &|& $", "", dt$error))
dt
a_check b_check error
1 20 0 A_CHECK must be one of the following values: 1, 2, 3
2 2 1
3 1 NA B_CHECK must be one of the following values: 0, 1
4 NA 1 A_CHECK must be one of the following values: 1, 2, 3
5 0 15 A_CHECK must be one of the following values: 1, 2, 3 & B_CHECK must be one of the following values: 0, 1
РЕДАКТИРОВАТЬ: на самом деле, вам, возможно, придется скорректировать шаблон регулярных выражений, если существует более двух переменных, чтобы удалить лишние &
.В противном случае, это должно хорошо масштабироваться.
Добавление еще одного оператора gsub
должно помочь (теоретически).
dt$error <- apply(dt_errors, 1 , paste, collapse = " & ")
dt$error <- gsub("( & )\\1+", "\\1", dt$error)
dt$error <- gsub("^ & | & $", "", dt$error)