データ フレーム内の名前の評価に依存する関数内で関数を呼び出す場合do.call
、関数に渡す前にその引数を評価する を使用するため、デバッグとコードの記述の両方がより簡単になり、それが何であるかについてより確実になるように感じます。やっています。(デバッグの場合は、call
代わりに を使用do.call
してください。これにより、関数が実行しようとする内容が表示されます。構文も少し異なるため、これを行う場合は、呼び出し内のリスト構造も削除します。)
(このアイデアに対する Josh O'Brien の回答へのクレジット: https://stackoverflow.com/a/7668846/210673 )
この場合、次のようになります。
test.fun <- function(x, data, event){
require(crrstep)
select.mod <- do.call("crrstep",
list(formula=x, etype=substitute(event), failcode=1, cencode=0,
data=as.name("data"), direction = "backward", criterion = "AIC",
crr.object = TRUE, trace = FALSE))
print(select.mod)
}
test.fun(x=formula1, data=testdata, event=fstatus)
はsubstitute(event)
、 name ではなく、関数に付けられた名前を使用するように指示しますevent
。は、実際のデータ フレームを渡すのではなく、関数内でas.name("data")
検索するように指示します。data
別のオプションはsubstitute(data)
、実際のデータ フレームを探すことです。
使用例lm
lm
とweights
引数を使用した非常によく似た動作の例を次に示します。
lm
別の関数内ではなく、サンプル データ セットと への呼び出しを次に示します。応答のcall
要素を出力して、実際に何が行われたかを確認します。
> set.seed(5)
> dd <- data.frame(x=1:10,y=round(rnorm(10,mean=10),1), z=round(runif(10,1,4),1))
> lm(y~x, weights=z, data=dd)$call
lm(formula = y ~ x, data = dd, weights = z)
w
データフレームで探しているため、機能しない自然な方法:
> f1 <- function(f,w,d){
+ lm(formula=f,weights=w, data=d)
+ }
> f1(y~x, z, dd)
Error in eval(expr, envir, enclos) : object 'w' not found
文字列を使用して呼び出しを構築できます。これはもう少し簡単です:
> f2 <- function(f,w,d){
+ do.call("lm", list(formula=as.formula(f), weights=as.name(w), data=as.name(d)))
+ }
> f2("y~x", "z", "dd")$call
lm(formula = y ~ x, data = dd, weights = z)
またはsubstitute
、 ;を使用できます。dd
ここでは、関数内ではなく、実際のデータ セットで関数を呼び出してd
います。これは、後で を使用する場合に役立つ可能性がありますupdate
。
> f3 <- function(f,w,d){
+ do.call("lm", list(formula=f, weights=substitute(w), data=substitute(d)))
+ }
> f3(y~x, z, dd)$call
lm(formula = y ~ x, data = dd, weights = z)
しかしd
、関数内で使用することもできます。今回data = d
は、呼び出しの代わりにdata = dd
.
> f4 <- function(f,w,d){
+ do.call("lm", list(formula=f, weights=substitute(w), data=as.name("d")))
+ }
> f4(y~x, z, dd)$call
lm(formula = y ~ x, data = d, weights = z)
実際のデータ フレームを挿入することもできますが、呼び出しは長くなります。ただし、各呼び出しの前にプログラムでデータ フレームを変更し、そのデータ フレームが何であるかを記録したい場合は、これが望ましい場合があります。(ただし、後で本当に必要な場合は、そのデータフレームをより明示的な方法で保存することをお勧めします。)
> f5 <- function(f,w,d){
+ do.call("lm", list(formula=f, weights=substitute(w), data=d))
+ }
> f5(y~x, z, dd)$call
lm(formula = y ~ x, data = list(x = 1:10, y = c(9.2, 11.4, 8.7,
10.1, 11.7, 9.4, 9.5, 9.4, 9.7, 10.1), z = c(3.7, 3.2, 1.6, 1.7,
1.4, 2.4, 2.3, 3.9, 1.4, 3.9)), weights = z)
の呼び出し内で が実行されるため、substitute
なしでは使用できないことを示すもう 1 つの例です。do.call
substitute
lm
> f6 <- function(f,w,d){
+ lm(formula=f,weights=substitute(w), data=d)
+ }
> f6(y~x, z, dd)
Error in model.frame.default(formula = f, data = d, weights = substitute(w), :
invalid type (symbol) for variable '(weights)'