编写函数时,检查参数类型很重要。例如,采用以下(不一定有用)执行子集化的函数:
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;必须工作。 这里有什么问题,有人能给我一个提示吗?
答案 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;但令人困惑,因为除非仔细阅读您的功能文档,否则我们会在第一种情况下获得col1
并col2
在第二种情况下。
滥用famous quote:
有些人在遇到问题时会想“我知道,我会使用非标准评估。”现在他们有两个问题。
Hadley Wickham Non-standard evaluation:
非标准评估允许您编写功能非常强大的功能。但是,他们更难理解和编程。除了始终提供逃生舱口之外,在新域名中使用NSE之前,请仔细考虑NSE的成本和收益。
除非您希望跳过列名称旁边的引号,否则请不要这么做。