Вы указали «выражение» в качестве класса второго аргумента в этом примере метода. Первый пример возвращает ошибку, потому что
NewVar=Petal.Width*Petal.Length
интерпретируется как именованный аргумент myfun со значением
Petal.Width*Petal.Length
, который не может быть оценен, потому что NewVar не является аргументом для этого метода или универсальным.
Во втором примере я не уверен, что происходит с закрытыми фигурными скобками, так как моя ошибка отличается от показанной:
Ошибка в myfun (радужная оболочка {:
ошибка в оценке аргумента 'y' при выборе метода для функции 'myfun': ошибка: объект 'Petal.Width' не найден
Однако я не получаю сообщение об ошибке и получаю радужную оболочку data.frame в качестве вывода, когда вы заставляете ваше выражение быть объектом выражения:
myfun(iris, expression(NewVar=Petal.Width*Petal.Length))
Я думаю, что это только частично отвечает на ваш вопрос, потому что тривиальный возврат iris data.frame был не тем, что вы хотели. Выражение не оценивается должным образом с помощью 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
Опять же, эта реализация по существу жестко запрограммировала, что один и только один столбец переменной будет добавлен во входной файл data.frame, хотя имя этого столбца переменной и выражение являются произвольными и предоставляются в качестве выражения. Я уверен, что есть лучший, более общий ответ, который оценил бы выражение, хранящееся в y, как если бы это был прямой вызов в функции transform (), но в настоящий момент я озадачен тем, что использовать в качестве соответствующего «обратного» "функция для выражения ().
Всегда есть стандарт ..., если вы не хотите отправлять на 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" "Виды"
По сути, часть выражения "NewVar =" не была передана transform (), когда мы вызвали 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", который мы хотели.