2011-08-09 9 views
11

S4メソッドに引数を使用するように納得させようとしていますが、私はいつもエラーを返します。引数として式を持つ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ディスパッチメソッドを使用する可能性はありますか?


編集:これは良い例です。

+1

SfDAの399-402ページを参照してください。ここで、Chambersは署名検証済みの引数を評価する必要がある理由を説明しています。 –

+0

@DWin:リンクを共有してみませんか? sfDAは私には馴染みのないように聞こえ、国家食品医薬品局(State Food and Drug Administration)について話しているわけではないと思います... –

+0

申し訳ありません。 John Chambersによる "データ解析用ソフトウェア"追加のポイントとして、私はあなたの署名値が引数名に関連付けられていないことに気付きましたが、例ではフォーマットです。 (注:あなたはまだ質問本体で 'transform'に変更していません) –

答えて

2

この例のメソッドでは、2番目の引数のクラスとして "expression"を指定しました。

NewVar=Petal.Width*Petal.Length 

がNewVarが引数ではありませんので、評価する機会を得ることはありません値

Petal.Width*Petal.Length 

とMYFUNする名前付き引数として解釈されているので、最初の例はエラーを返しますこのメソッドまたは汎用の場合2番目の例では

私のエラーが示されたものと異なるので、私は、閉じ中括弧で何が起こっているかわからないんだけど:myfunはつぎで

エラー(アイリス、{:評価で エラーエラー:オブジェクト 'Petal.Width'が見つかりません。

しかし、私は式を強制するとエラーは発生せず、iris data.frameを出力として取得します。これは、関数 'myfun'表現オブジェクト:

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

ここには、データに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" "種" "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に追加されることは本質的にハードコードされています。私はtransform()関数の直接呼び出しであるかのように、yで保持されている式を評価する、より良い、より一般的な答えがあると確信していますが、現時点では、適切な "inverse式()への関数。

あなたが実際の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()に渡されませんでした。

多くの試行錯誤の末、私は実際に働く方法を考え出しました。

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" 

そして新しい:最初の完全な例は次のようになります素晴らしい

do.call() 

にしたいコールを構築し、その後、)(as.listでリストに表現オブジェクトを変換data.frameオブジェクト "test"には、必要な "NewVar"カラムがあります。

+1

evalは、ネストされた関数を持つときに全く新しい一連の問題を引き起こします。環境...私はそれをハードコードすることができますが、ポイントは本質的に私のS4オブジェクトのための変換の柔軟性を持っていることです。私はS3メソッドを使って解決しましたが、私は特に画面の後ろで何が起こっていたかに興味がありました... –

+1

はい、私はevalと同じ問題を発見していました。私は私があなたの問題のために働くかもしれないdo.callのアプローチを追加したと思います。 –

+1

最高の回避策を見つけることができました。 –

1

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

"within"のヘルプを見ると、中括弧が使用され、式が式として解析されているかどうかが確認されます。

私も、私も、私は表現について十分に知っていないと思います

...機能内部に呼び出すと、関数の呼び出し側で交換をしないと思います。

+0

'expr'は複数の式の意味での複数行の式なので、中括弧だけではありませんか?単一のR式を指定する場合、 'within()'に中カッコを入れる必要はありません。 –

+0

名前付きのパラメータや式に関するあなたの意見は面白いです。これは、割り当てとしての '='と '< - 'の不等式が、お尻のジョリスを噛んでいる時でしょうか? IIRCでは 'within 'に' <-'を使用する必要があります。 '='は代入として機能しません。 –

+0

試してみてください:うまくいきません。 '< - 'を使うのと同じです。 –

関連する問題