2011-12-15 4 views
1

これは私がやりたいことの非常にトリミングされたバージョンです。コードが長すぎると複雑なので、私は正確な問題を貼り付けることができませんが、これは問題の根本にあると思います。この質問へのジョシュの答えのおかげでHow do you code an R function so that it 'knows' to look in 'data' for the variables in other arguments?私はそこに途中です。どのように関数内の 'formula'型のオブジェクトに(ベクトル名など)を追加できますか?

example <- function(model, xvar3=NULL, xvar4=NULL, data){ 
    print(class(model)) 
    #xvar3 <- eval(substitute(xvar3), envir=data, enclos=parent.frame()) 
    #xvar4 <- eval(substitute(xvar4), envir=data, enclos=parent.frame()) 
    print(class(xvar3)) 
    xvar5 <- xvar4^2 
    mod <- glm(model + xvar3 + xvar5, data=data)  
    return(mod) 
} 

example(mpg ~ cyl, hp, wt, data=mtcars) 

これは失敗します。コメントを削除すると(前の質問の助けに基づいて)、hpとwtを見つけることの問題を解決します。 'model'はクラス式で、glmが動くように 'mpg〜cyl + xvar3 + xvar5'になりたいです。しかし、私は数式にそれらを追加することができないようです。

私は '呼び出し'クラス、さらには 'eval'、 'as.formula'のバリエーションを 'paste'や 'noquote'などで取り組んできましたが、固執することはありません。

+0

起動時に 'update'を使うだけでいいです.... –

+0

おかげで、最初の遊びでは、「単語」xvar3が正しく表示されずデータの実際のベクトルが印刷されています。それはおそらく非常に貧弱です。 – nzcoops

+0

重要なのは、モデルに用語を追加することです。それが 'update'の目的です。基本的に、あなたは車輪を再発明しているようです。 –

答えて

2

ここには1つの方法があります。私が使用したトリックは、与えられた1つの+ 2つの余分な変数に基づいて新しい式を作成することです。私はその後、式の環境を使って、xvar3/xvar5と呼び出し元のローカル変数を使用できるようにしました。

glmは、常にフォーミュラの環境と変数のデータ(とどこにもありません!)を見ます。そのため、数式環境では、この場合は少し操作する必要があります:xvar3xvar5があり、親環境が元の数式環境に設定されているため、変数も検索されます(最後の例ではfoo)...

example <- function(model, xvar3=NULL, xvar4=NULL, data){ 
    e <- new.env(parent=environment(model)) 
    e$xvar3 <- eval(substitute(xvar3), envir=data, enclos=parent.frame()) 
    e$xvar4 <- eval(substitute(xvar4), envir=data, enclos=parent.frame()) 
    e$xvar5 <- e$xvar4^2 

    model <- update(model, . ~ . + xvar3 + xvar5) 
    environment(model) <- e 

    mod <- glm(model, data=data) 

    return(mod) 
} 

example(mpg ~ cyl, hp, wt, data=mtcars) 

# Using a local variable should work too: 
doit <- function(d) { 
    foo <- d$cyl+1 
    example(mpg ~ foo, hp, wt, data=d) 
} 
doit(mtcars) 
+0

式 'call'オブジェクトを直接混乱させるのではなく、' update'を使うように編集しました。 – Tommy

+0

私はあなたがデータを動かすのではなく、式を操作する方が良いと思います。 – hadley

+0

@hadley - そうですね、数式で新しいデータを表現できる場合(ここでは「wt^4」など)、他のデータをマージする必要がある場合は、このようなものが必要です。別の方法として、新しい列 'xvar5'などを' data.frame'に追加する方法があります。 – Tommy

1

は、ここで私はそれを行うだろう方法は次のとおりです。

add_vars <- function(model, xvar3=NULL, xvar4=NULL, data){ 
    # Capture the unevalated calls to xvar3 and xvar4 
    xvar3 <- substitute(xvar3) 
    xvar4 <- substitute(xvar4) 

    # Use substitute to create the correct formula to supply to update 
    update_f <- eval(substitute(. ~ . + xvar3 + I(xvar4^2), 
    list(xvar3 = xvar3, xvar4 = xvar4))) 

    # Modify the original formula string 
    update(model, update_f) 
} 

add_vars(mpg ~ cyl, hp, wt) 
# mpg ~ cyl + hp + I(wt^2) 
0

(同僚から)、このための別のオプション:

example <- function(model, xvar3=NULL, xvar4=NULL, data){ 

    data$xvar3 <- eval(substitute(xvar3), envir=data, enclos=parent.frame()) 
    data$xvar4 <- eval(substitute(xvar4), envir=data, enclos=parent.frame()) 
    data$xvar5 <- data$xvar4^2 

    model <- as.formula(paste(model[2], paste(model[3], "xvar4","xvar5", sep="+"), sep="~")) 
    mod <- glm(model, data=data) 
    return(mod) 
} 

example(mpg ~ cyl, hp, wt, data=mtcars) 

私はこれがとても好きです。

関連する問題