このサンプルメソッドでは、2番目の引数のクラスとして「expression」を指定しました。最初の例では、次の理由でエラーが返されます。
NewVar=Petal.Width*Petal.Length
値を持つmyfunへの名前付き引数として解釈されています
Petal.Width*Petal.Length
NewVarはこのメソッドまたはジェネリックの引数ではないため、評価される機会はありません。
2番目の例では、私のエラーが示されているものとは異なるため、閉じた中括弧で何が起こっているのかわかりません。
myfun(iris、{:関数'myfun'のメソッドを選択する際の引数'y'の評価エラー:エラー:オブジェクト'Petal.Width'が見つかりません
ただし、式を式オブジェクトに強制すると、エラーは発生せず、出力としてirisdata.frameが取得されます。
myfun(iris, expression(NewVar=Petal.Width*Petal.Length))
アイリス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に1つの変数列を追加するために機能するバージョンは次のとおりです。
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" "Species" "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
この場合も、この実装では基本的に1つだけの変数列が入力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""種"
基本的に、myfun()を呼び出したときに、式の「NewVar =」部分がtransform()に渡されませんでした。
多くの試行錯誤の末、私は実際に機能する方法を見つけました。最初に式オブジェクトを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」列があります。