11

S4メソッドに式を引数として使用するように説得しようとしていますが、常にエラーが返されます。私がここでやろうとしていることを少し説明する簡単な例:

setGeneric('myfun',function(x,y)standardGeneric('myfun'))

setMethod('myfun',c('data.frame','expression'),
          function(x,y) transform(x,y) )

私が今試してみると:

> myfun(iris,NewVar=Petal.Width*Petal.Length)
Error in myfun(iris, NewVar = Petal.Width * Petal.Length) : 
  unused argument(s) (NewVar = Petal.Width * Petal.Length)

> myfun(iris,{NewVar=Petal.Width*Petal.Length})
Error in myfun(iris, list(NewVar = Petal.Width * Petal.Length)) : 
 error in evaluating the argument 'y' in selecting a method for 
 function 'myfun': Error: object 'Petal.Width' not found

私が正しく理解していれば、引数はすでにジェネリックで評価されているようです。したがって、式をメソッドに渡すことは、少なくとも注意が必要なようです。式を使用してS4ディスパッチメソッドを使用する可能性はありますか?


編集:より良い例であるため、変換に変更されました。

4

2 に答える 2

2

このサンプルメソッドでは、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」列があります。

于 2011-09-10T08:41:26.780 に答える
1

名前付きパラメーターを渡すつもりなのか、式がa = bの形式なのかをRが判断できないのは、S4や引数の評価ではありません。

「within」のヘルプを見ると、中かっこを使用して、式が式として解析されていることを確認しています。

また、関数内で呼び出しても、関数の呼び出し元では置換されないと思います...

また、表現についてはよくわからないと思います。

于 2011-08-09T17:08:29.110 に答える