检查函数的表达式参数

Check expression argument of function

编写函数时,检查参数类型很重要。例如,采用以下(不一定有用)执行子集化的函数:

data_subset = function(data, date_col) {

      if (!TRUE %in% (is.character(date_col) | is.expression(date_col))){
        stop("Input variable date is of wrong format")
      }

      if (is.character(date_col)) {
        x <- match(date_col, names(data))
      } else  x <- match(deparse(substitute(date_col)), names(data))

        sub <- data[,x]
}

我想允许用户提供应提取为字符或表达式的列(例如,名为 "date" 的列与日期)。一开始我想检查 date_col 的输入是否真的是字符值或表达式。但是,'is.expression' 不起作用:

Error in match(x, table, nomatch = 0L) : object '...' not found

因为 deparse(substitute)) 如果提供表达式就可以工作,我认为 'is.expression' 也必须工作。 这里有什么问题,谁能给我提示?

我认为您不是在寻找 is.expression,而是在寻找 is.name

棘手的部分是获取 date_col 的类型并检查它是否是字符类型,只有当它 不是 类型时才检查 name .如果您在 is.character 是名称时调用它,那么它会被评估,通常会导致错误,因为该对象未定义。

为此,可以使用short circuit evaluation:In

if(!(is.name(substitute(date_col)) || is.character(date_col)))

is.character 仅在 is.name returns FALSE.

时调用

你的函数归结为:

data_subset = function(data, date_col) {

  if(!(is.name(substitute(date_col)) || is.character(date_col))) {
     stop("Input variable date is of wrong format") 
  }

  date_col2 <- as.character(substitute(date_col))
  return(data[, date_col2])
}

当然,当date_col是一个名字时,你可以使用if(is.name(…))只转换为字符。

这个有效:

testDF <- data.frame(col1 = rnorm(10), col2 = rnorm(10, mean = 10), col3 = rnorm(10, mean = 50), rnorm(10, mean = 100))

data_subset(testDF, "col1") # ok
data_subset(testDF, col1) # ok
data_subset(testDF, 1) # Error in data_subset(testDF, 1) : Input variable date is of wrong format

但是,我认为您不应该这样做。考虑以下示例:

var <- "col1"
data_subset(testDF, var) #  Error in `[.data.frame`(data, , date_col2) : undefined columns selected

col1 <- "col2"
data_subset(testDF, col1) # Gives content of column 1, not column 2.

尽管这个 "works as designed" 令人困惑,因为除非仔细阅读函数的文档,否则人们会期望在第一种情况下得到 col1,在第二种情况下得到 col2

滥用 famous quote:

Some people, when confronted with a problem, think “I know, I'll use non-standard evaluation.” Now they have two problems.

Non-standard evaluation 中的哈德利·韦翰:

Non-standard evaluation allows you to write functions that are extremely powerful. However, they are harder to understand and to program with. As well as always providing an escape hatch, carefully consider both the costs and benefits of NSE before using it in a new domain.

除非您期望允许跳过列名称周围的引号会带来很大好处,否则不要这样做。