Ответ 1
Вы указали "выражение" как класс второго аргумента в этом примере. Первый пример возвращает ошибку, поскольку
NewVar=Petal.Width*Petal.Length
интерпретируется как именованный аргумент myfun со значением
Petal.Width*Petal.Length
который не получает возможности быть оцененным, потому что NewVar не является аргументом для этого метода или общего.
Во втором примере я не уверен, что происходит с закрытыми фигурными фигурными скобками, так как моя ошибка отличается от приведенной:
Ошибка в myfun (iris, {: ошибка в оценке аргумента 'y' при выборе метода для функции 'myfun': Ошибка: объект 'Petal.Width' не найден
Однако я не получаю ошибки и получаю iris data.frame как вывод, когда я заставляю ваше выражение быть объектом выражения:
myfun(iris, expression(NewVar=Petal.Width*Petal.Length))
Я думаю, что это лишь частично отвечает на ваш вопрос, потому что тривиальное возвращение данных диафрагмы. Это не то, что вы хотели. Выражение не оценивается должным образом методом transform(). Я подозреваю, что вы хотите, чтобы результат точно соответствовал выводам из следующей версии с жестким кодированием:
transform(iris, NewVar=Petal.Width*Petal.Length)
Вот краткий пример оценки выражения с использованием eval
z <- expression(NewVar = Petal.Width*Petal.Length)
test <- eval(z, iris)
head(test, 2)
[1] 0,28 0,28
Вот версия, которая работает для добавления одного столбца переменной в файл data.frame:
setGeneric('myfun',function(x,y)standardGeneric('myfun'))
setMethod('myfun',c('data.frame','expression'), function(x,y){
etext <- paste("transform(x, ", names(y), "=", as.character(y), ")", sep="")
eval(parse(text=etext))
})
## now try it.
test <- myfun(iris, expression(NewVar=Petal.Width*Petal.Length))
names(test)
[1] "Sepal.Length" "Sepal.Width" "Petal.Length" "Petal.Width" "Породы" "NewVar"
head(test)
Sepal.Length Sepal.Width Petal.Length Petal.Width Species NewVar
1 5.1 3.5 1.4 0.2 setosa 0.28
2 4.9 3.0 1.4 0.2 setosa 0.28
Опять же, эта реализация по существу жестко закодирована, что один и только один столбец переменной будут добавлены во входной файл данных, хотя имя столбца этой переменной и выражение произвольны и представлены как выражение. Я уверен, что есть лучший, более общий ответ, который оценил бы выражение, содержащееся в y, как если бы это был прямой вызов в функции transform(), но в настоящий момент я озадачен тем, что использовать в качестве подходящего "обратного" function to expression().
Всегда есть стандарт..., если вы действительно не хотите отправлять y:
setGeneric('myfun', function(x, ...) standardGeneric('myfun'))
setMethod('myfun', 'data.frame', function(x, ...){
transform(x, ...)
})
И это отлично работает. Но ваш вопрос заключался в том, чтобы фактически отправлять объект выражения.
Следующее не работает, но я думаю, что он приближается. Возможно, кто-то может вскочить и сделать некоторые окончательные настройки:
setGeneric('myfun', function(x, y) standardGeneric('myfun'))
setMethod('myfun',c('data.frame', 'expression'), function(x, y){
transform(x, eval(y, x, parent.frame()))
})
## try out the new method
z <- expression(NewVar = Petal.Width*Petal.Length)
test <- myfun(iris, z)
names(test)
[1] "Sepal.Length" "Sepal.Width" "Petal.Length" "Petal.Width" "Species"
По существу, часть "NewVar =" выражения не передавалась преобразованию(), когда мы вызывали myfun().
После долгих проб и ошибок я понял, как это работает. Сначала преобразуйте объект выражения в список с помощью as.list(), а затем создайте вызов, который вы хотите, с чудесным
do.call()
Полный пример выглядит следующим образом:
setGeneric('myfun', function(x, y) standardGeneric('myfun'))
setMethod('myfun',c('data.frame', 'expression'), function(x, y){
do.call("transform", c(list(x), as.list(y)))
})
# try out the new method
z <- expression(NewVar = Petal.Width*Petal.Length)
test <- myfun(iris, z)
names(test)
[1] "Sepal.Length" "Sepal.Width" "Petal.Length" "Petal.Width" "Species"
[6] "NewVar"
И новый объект data.frame "test" имеет нужный столбец "NewVar".