2012-10-19 12 views
50

他の人の関数は数式オブジェクトを取って、暗い魔法を彼らのどこかに深く入れ、私は嫉妬しているようです。プログラムで式を構築するには、文字列操作より優れた方法がありますか?

私は複数のモデルに適合する関数を書いています。これらのモデルの数式の一部は同じままであり、あるモデルから次のモデルに変更されています。不器用な方法は、ユーザーに文字列として式の部分を入力させ、文字を操作してからas.formulaを使用することです。

しかし、私はそのルートに入る前に、関数が標準のRフォーマットの式を受け入れるような、より洗練された方法を見落としていないことを確認したいだけです。オブジェクト)。

私は何かのような...

> LHS <- y~1; RHS <- ~a+b; c(LHS,RHS); 
y ~ a + b 
> RHS2 <- ~c; 
> c(LHS, RHS, RHS2); 
y ~ a + b + c 

か...

​​

をしたい...残念ながらどちらの構文は動作します。誰かが何かがあるかどうか知っていますか?ありがとう。

+0

私はかなりのレベルの一般性を必要とせず、代わりに 'update'関数を使いやすくしたにもかかわらず、下記のmnelの答えは役に立ちました。私はもともと試していた。しかし一般的に、私は良い回答をアップアップしますが、私が実際に試してみるまで受け入れず、それらを保証することができます。多くの場合、私は自分自身でより良い答えを見つけ、時間があるときに本当に自己回答を提出すべきです。私は答えを受け入れるための私の基準にあまりにも厳しいですか? – f1r3br4nd

答えて

62

reformulateあなたがしたいことをします。あなたは(あなたの例与えられた)既存のformulaから用語を抽出するには、このようなx+y ~z+b

reformulate(termlabels = c('x','y'), response = c('z','b')) 
z ~ x + y 

など、複数のreponsesで式を構築することができないことを

reformulate(termlabels = c('x','z'), response = 'y') 
## y ~ x + z 

またはインターセプト

reformulate(termlabels = c('x','z'), response = 'y', intercept = FALSE) 
## y ~ x + z - 1 

注意なし

attr(terms(RHS), 'term.labels') 
## [1] "a" "b" 

応答を取得するには、単純なアプローチ(1つの変数応答の場合)が少し異なります。

as.character(LHS)[2] 
## [1] 'y' 


combine_formula <- function(LHS, RHS){ 
    .terms <- lapply(RHS, terms) 
    new_terms <- unique(unlist(lapply(.terms, attr, which = 'term.labels'))) 
    response <- as.character(LHS)[2] 

    reformulate(new_terms, response) 


} 


combine_formula(LHS, list(RHS, RHS2)) 

## y ~ a + b + c 
## <environment: 0x577fb908> 

私はあなたにものための新たな方法を設定する式(アップデートで動作するように+オペレータを定義することができ、文字ベクトルとして応答を指定する方が賢明だろう

combine_formula2 <- function(response, RHS, intercept = TRUE){ 
    .terms <- lapply(RHS, terms) 
    new_terms <- unique(unlist(lapply(.terms, attr, which = 'term.labels'))) 
    response <- as.character(LHS)[2] 

    reformulate(new_terms, response, intercept) 


} 
combine_formula2('y', list(RHS, RHS2)) 

のようなものを考えます式オブジェクト)あなたはまた、慎重に.を使用してupdate.formulaを使用することができます

`+.formula` <- function(e1,e2){ 
    .terms <- lapply(c(e1,e2), terms) 
    reformulate(unique(unlist(lapply(.terms, attr, which = 'term.labels')))) 
} 

RHS + RHS2 
## ~a + b + c 

update(~a+b, y ~ .) 
## y~a+b 
+9

+1あなたの偉大な要約。ただし、コードを読みやすくするためには、文字列によるアプローチを使用する方法があります。私は、生涯にわたって合計されると、スピードの向上はあなたにコーヒーの時間を買うことを疑う。 –

+16

@DieterMenne速度の向上は重要ではありません。安全性の向上が重要です。誰かが構文上の変数名(つまり "a")を使用してコードを使用しようとすると、何時間も時間がかかる奇妙なエラーが発生します。 – hadley

+0

'.'を' update.formula'よりも使う方法はありますか?私は、 '〜。var1-var2'を' reformulate() 'で使うのが好きだった' setdiff() 'ステートメントを使ってしまいました。 –

関連する問題