检查函数的表达式参数

时间:2015-07-13 09:43:18

标签: r function arguments expression

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

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]
}

我想允许用户提供应该提取为字符或表达式的列(例如,名为&#34; date&#34; vs just date)的列。一开始我想检查date_col的输入是字符值还是表达式。然而,&#39; is.expression&#39;不起作用:

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

由于deparse(substitute))如果有人提供表达式,我认为是'is.expression&#39;必须工作。 这里有什么问题,有人能给我一个提示吗?

1 个答案:

答案 0 :(得分:1)

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

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

为此,可以使用short circuit evaluation

if(!(is.name(substitute(date_col)) || is.character(date_col)))
仅当is.character返回is.name时才会调用{p> 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])
}

当然,当if(is.name(…))是名称时,您可以使用date_col仅转换为字符。

这有效:

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.

虽然这&#34;按设计工作&#34;但令人困惑,因为除非仔细阅读您的功能文档,否则我们会在第一种情况下获得col1col2在第二种情况下。

滥用famous quote

  

有些人在遇到问题时会想“我知道,我会使用非标准评估。”现在他们有两个问题。

Hadley Wickham Non-standard evaluation

  

非标准评估允许您编写功能非常强大的功能。但是,他们更难理解和编程。除了始终提供逃生舱口之外,在新域名中使用NSE之前,请仔细考虑NSE的成本和收益。

除非您希望跳过列名称旁边的引号,否则请不要这么做。