Пакеты tibble
и rlang
, часть tidyverse
, имеют функцию для проверки этого:
library(tibble) # or library(rlang) or library(tidyverse)
has_name(iris, c("Species","potatoe"))
# [1] TRUE FALSE
Технически он живет в rlang
и его код просто:
function (x, name)
{
name %in% names2(x)
}
, где rlang::names2
- это расширенная версия base::names
, которая возвращает вектор пустых строк, а не NULL
, когда у объекта нет имен.
Вот способ переписать вашу функцию:
validate_df_columns <- function(df, columns){
if (!is.data.frame(df)) {
stop(paste("Argument", deparse(substitute(df)), "must be a data.frame."))
}
if(!all(i <- rlang::has_name(df,columns)))
stop(sprintf(
"%s doesn't contain: %s",
deparse(substitute(df)),
paste(columns[!i], collapse=", ")))
}
validate_df_columns(iris, c("Species","potatoe","banana"))
# Error in validate_df_columns(iris, c("Species", "potatoe", "banana")) :
# iris doesn't contain: potatoe, banana
Использование deparse(substitute(...))
здесь не имеет большого смысла для меня, хотя, поскольку оно не используется в интерактивном режиме, на мой взгляд, яснее просто сказать "df"
.