Ответ с Eval и замена
Я думаю, что сделать это в этом случае вам просто нужно 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 ...
В предлагаемом редактировании, @ user2103369 предполагает, что replicate
отличается тем, что он использует sapply
получить несколько оценок, поэтому она нуждается в функции, а не вызов.
Различного поведение, когда аргумент по умолчанию
Интересно, что обещание действует по-разному в зависимости от того, если аргумента является аргументом или добавлен пользователем по умолчанию; Смотри ниже. Я думаю, что SoDA решает это, но у меня нет его под рукой. Эта функция печатает значение обещания, оценивает его с помощью eval
, а затем оценивает его напрямую.
foo <- function(a, b=a+1) {
print(substitute(b))
print(eval(substitute(b)))
b
}
Оценка его непосредственно приводит к ошибке, когда пользователь поставляет это значение.
> foo(a=2, b=a+1)
a + 1
[1] 3
Error in foo(a = 2, b = a + 1) : object 'a' not found
Но значение по умолчанию работает.
> foo(a=2)
a + 1
[1] 3
[1] 3
В предлагаемом редактировании, @ user2103369 говорит, что аргумент по умолчанию вычисляется внутри функция, в то время как явный аргумент вычисляется в вызывающем кадре. Таким образом, в этом случае значение, предоставленное пользователем, терпит неудачу, потому что a
не отображается в вызывающем фрейме.
Альтернативный метод с использованием функции
Однако для меня (хотя ОП не согласен, я оставляю эту часть для будущих читателей этого ответа), это чувствует, как случай, где это более естественно использовать как второй параметр; для одного, это означает, что пользователь не должен знать, что он называется 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)
}
Тогда его можно назвать с анонимной функцией, которая является именно то, что вы ищете, я думаю, за исключением того, что пользователь должен ввести 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 ...
Или в простых случаях, как в вашем примере, только с именем функции.
> 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 ...
О том, что 'replicate' делает, я ничего не проверял, но я думаю, что' функцию (...) 'способ передать дополнительные параметры в выражении, и' eval.parent' оценивает его в родительской среде, а не в среде функций. Вероятно, это будет причина, по которой это не будет работать в вашем случае, поскольку 'dat' не находится в родительской среде. – Aaron
Кроме того, в предлагаемом редактировании @ user2103369 предполагает, что 'replicate' отличается, потому что он использует' sapply' для получения нескольких оценок, поэтому ему нужна функция, а не вызов. – Aaron