我创建了以下函数/示例作为在表中显示变量标签的通用方法,依此类推:
#' Function to prettify the output of another function using a `var.labels` attribute
#' This is particularly useful in combination with read.dta et al.
#' @param dat A data.frame with attr `var.labels` giving descriptions of variables
#' @param expr An expression to evaluate with pretty var.labels
#' @return The result of the expression, with variable names replaced with their labels
#' @examples
#' testDF <- data.frame( a=seq(10),b=runif(10),c=rnorm(10) )
#' attr(testDF,"var.labels") <- c("Identifier","Important Data","Lies, Damn Lies, Statistics")
#' prettify( testDF, quote(str(dat)) )
prettify <- function( dat, expr ) {
labels <- attr(dat,"var.labels")
for(i in seq(ncol(dat))) colnames(dat)[i] <- labels[i]
attr(dat,"var.labels") <- NULL
eval( expr )
}
Run Code Online (Sandbox Code Playgroud)
但是,我宁愿用户不必引用传入的表达式.
replicate
就是这样,使用这段代码:
eval.parent(substitute(function(...) expr))
Run Code Online (Sandbox Code Playgroud)
然而,我不明白它是如何工作的,并且正如尝试复制而不理解一样,我试图简单地复制这些代码或修补它都失败了.
如何使用未评估的表达式作为输入编写函数,而无需用户quote
表达?我认为答案将严重依赖于懒惰的评估.
我认为在这种情况下你只需要这样做eval(substitute(expr))
. expr
是一个承诺,我们可以通过使用expr
直接使用或承诺的内容来获得承诺的价值substitute
.有关详细信息,请参见http://cran.r-project.org/doc/manuals/R-lang.html#Promise-objects.承诺的内容是一个call
,所以我们只是eval
为了得到新的结果.
prettify <- function( dat, expr ) {
labels <- attr(dat,"var.labels")
for(i in seq(ncol(dat))) colnames(dat)[i] <- labels[i]
attr(dat,"var.labels") <- NULL
eval(substitute(expr))
}
> prettify( testDF, str(dat))
'data.frame': 10 obs. of 3 variables:
$ Identifier : int 1 2 3 4 5 6 7 8 9 10
$ Important Data : num 0.336 0.9479 0.1379 0.94 0.0484 ...
$ Lies, Damn Lies, Statistics: num 1.398 0.654 0.268 -0.397 -0.41 ...
Run Code Online (Sandbox Code Playgroud)
在建议的编辑中,@ user2103369建议replicate
不同,因为它用于sapply
获得多个评估,因此它需要一个函数而不是一个调用.
有趣的是,承诺的行为会有所不同,具体取决于参数是默认参数还是由用户添加; 见下文.我认为SoDA解决了这个问题,但我没有把握它.此函数打印promise的值,对其求值eval
,然后直接对其求值.
foo <- function(a, b=a+1) {
print(substitute(b))
print(eval(substitute(b)))
b
}
Run Code Online (Sandbox Code Playgroud)
当用户提供值时,直接评估它会导致错误.
> foo(a=2, b=a+1)
a + 1
[1] 3
Error in foo(a = 2, b = a + 1) : object 'a' not found
Run Code Online (Sandbox Code Playgroud)
但默认值有效.
> foo(a=2)
a + 1
[1] 3
[1] 3
Run Code Online (Sandbox Code Playgroud)
在建议的编辑中,@ user2103369表示在函数内部计算默认参数,而在调用帧中计算显式参数.因此,在这种情况下,用户提供的值失败,因为a
在调用帧中不可见.
然而,对我来说(虽然OP不同意;我将这部分留给未来的读者回答这个问题),这感觉就像是一个使用函数作为第二个参数更自然的情况,就像这样; 例如,这意味着用户不必知道它dat
在函数内被调用.
prettify <- function( dat, FUN ) {
f <- match.fun(FUN)
labels <- attr(dat,"var.labels")
for(i in seq(ncol(dat))) colnames(dat)[i] <- labels[i]
attr(dat,"var.labels") <- NULL
f(dat)
}
Run Code Online (Sandbox Code Playgroud)
然后可以使用匿名函数调用它,我认为这正是您正在寻找的,除了用户也必须键入function(x)
.
> prettify( testDF, function(x) str(x) )
'data.frame': 10 obs. of 3 variables:
$ Identifier : int 1 2 3 4 5 6 7 8 9 10
$ Important Data : num 0.296 0.707 0.883 0.821 0.724 ...
$ Lies, Damn Lies, Statistics: num -1.1506 0.4846 -1.824 -0.397 0.0898 ...
Run Code Online (Sandbox Code Playgroud)
或者在简单的情况下,如在您的示例中,仅使用函数的名称.
> prettify( testDF, str)
'data.frame': 10 obs. of 3 variables:
$ Identifier : int 1 2 3 4 5 6 7 8 9 10
$ Important Data : num 0.296 0.707 0.883 0.821 0.724 ...
$ Lies, Damn Lies, Statistics: num -1.1506 0.4846 -1.824 -0.397 0.0898 ...
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
866 次 |
最近记录: |