私の核となる質問を説明するための再現可能で単純化された例:
引数としてベクトルを持つ関数から始めますfVec <- function(v) v[1]*v[2]
。
比較のために、明示的なパラメーターを使用して同じ関数を表現する直接的な方法は次のとおりfDirect <- function(a, b) a*b
です。
私のユースケースでは、fDirect
上記のように明示的なパラメーターを使用して関数を作成したいのですが、初期関数を呼び出して実装しますfVec
。したがって、この目的のために、次のように定義しfIndirect <- function(a, b) fVec(c(a, b))
ました。(私がなぜそのようなことをしたいのかを以下に説明しますが、明らかに意味がありません!)
予想どおり、fVec(c(2, 3))
、fDirect(2, 3)
、およびfIndirect(2, 3)
6 が返され、これまでのところ良好です。
プロットの目的で、次のように、プロットするデータを含むデータ フレームを作成します。
- 関数パラメーター値を作成します
mydf <- data.frame(a=1:3, b=2:4)
。 - を使用して新しい列に関数値を追加します
transform
。
を使用するfDirect
と、transform(mydf, v=fDirect(a, b))
期待どおりに動作し、次のように返されます。
> transform(mydf, v=fDirect(a, b))
a b v
1 1 2 2
2 2 3 6
3 3 4 12
ただし、 を使用するfIndirect
と、目的の関数値が返されません。
> transform(mydf, v=fIndirect(a, b))
a b v
1 1 2 2
2 2 3 2
3 3 4 2
デバッグ中に、 を使用して、列とデータ フレームの和集合であるベクトル引数にfIndirect
渡さtransform
れることに気付きました。その結果、最初の 2 つの要素の積を評価して、すべての行を返します。fVec
a
b
c(mydf[["a"]], mydf[["b"]])
fVec
1*2=2
これまでのところ、この課題を回避するために思いついた最善の解決策は、次のように使用することでした。transform
apply
cbind(mydf, v=apply(mydf, 1, function(row) fIndirect(row["a"], row["b"])))
質問:一度に 1 行ずつ関数を評価する場所で呼び出した場合と同じように動作するのではなく、transform
両方のデータ フレーム列をfVec
スルーなぜそれは R のバグですか、それともスコープや引数のキャストに関する何かのように R が動作する方法で何か基本的なことを誤解していますか?fIndirect
fDirect
コンテキスト:
このセクションでは、私がそのようなプロセスに従う理由を説明します。
最適化しようとするかなり複雑な目的関数 (つまり、fVec
役割) があります。この関数には、この関数を使用するさまざまな方法、特に目的関数の引数としてベクトルを期待する BBoptim オプティマイザーの使用において便宜上、名前付きベクトル引数として渡される可変数のパラメーターがあります。
変数パラメーターの数が 1 または 2 の場合、目的関数をプロットしたい場合があります ( plot
1 次元の場合は使用し、2 次元の場合は格子パッケージのlevelplot
andを使用します)。wireframe
fIndirect
次に、データ フレーム (つまり、ロール) にプロットするデータを作成するのに便利なように、明示的なパラメーター (つまり、ロール) を使用して一時的な関数を作成しますmydf
。私の目的関数は比較的複雑で、ベクトル引数を持つバージョンが必要なのでfIndirect
、元の目的関数を呼び出して一時関数を実装したいと思いますfVec
。
上記の簡単な例で示したプロセスよりも、同じ目標を達成するためのより良い方法を提案できる人はいますか?