2016-06-15 6 views
6

今、私は組み込みのデータセットアイリスからコンボを持っています。これまでは、一対の値のlm()の係数を見つけることができるように導かれました。R:データセットのコンビネーションからより複雑な計算を実行する方法は?

myPairs <- combn(names(iris[1:4]), 2) 

formula <- apply(myPairs, MARGIN=2, FUN=paste, collapse="~") 

model <- lapply(formula, function(x) lm(formula=x, data=iris)$coefficients[2]) 

model 

しかし、私はさらにいくつかのステップを進めて、さらに計算に使用するlm()の係数を使用したいと思います。

Coefficient <- lm(formula=x, data=iris)$coefficients[2] 
Spread <- myPairs[1] - coefficient*myPairs[2] 
library(tseries) 
adf.test(Spread) 

手順自体は十分に簡単ですが、私は、データセット内の各combnのためにこれを行う方法を見つけることができませんでした:私はこのような何かをしたいと思います。 (sidenoteとして、adf.testはそのようなデータには適用されませんが、デモのためにアイリスデータセットを使用しています)。 私は、このような手順のループを書くほうがよいでしょうか?

+1

ek。ループを使用することなく、各組み合わせに対して結果(具体的には最後の4行)を提供するソリューションが必要です。そうですか? –

+1

私はあなたの2番目のブロックで少し混乱しています。すべてのペアのスプレッドを計算しますか?最後に何が起こるのですか( 'myPairs [6] - 係数*' ???)? – TARehman

+0

@AnalyticalMonkはい、そうです。ループが効率的であれば、私はそれを書いても構いません。 –

答えて

2

combnの中でこれを行うことができます。あなただけのすべての組み合わせの上に回帰を実行したい場合は

、そしてあなたが

fun <- function(x) coef(lm(paste(x, collapse="~"), data=iris))[2] 
combn(names(iris[1:4]), 2, fun) 

を行うことが第2の係数を抽出その後、

fun <- function(x) { 
     est <- coef(lm(paste(x, collapse="~"), data=iris))[2] 
     spread <- iris[,x[1]] - est*iris[,x[2]] 
     adf.test(spread) 
     } 

out <- combn(names(iris[1:4]), 2, fun, simplify=FALSE) 
out[[1]] 

# Augmented Dickey-Fuller Test 

#data: spread 
#Dickey-Fuller = -3.879, Lag order = 5, p-value = 0.01707 
#alternative hypothesis: stationary 

結果を比較広がりを計算する機能を拡張することができます手動で最初のものを実行するには

est <- coef(lm(Sepal.Length ~ Sepal.Width, data=iris))[2] 
spread <- iris[,"Sepal.Length"] - est*iris[,"Sepal.Width"] 
adf.test(spread) 

# Augmented Dickey-Fuller Test 

# data: spread 
# Dickey-Fuller = -3.879, Lag order = 5, p-value = 0.01707 
# alternative hypothesis: stationary 
+1

ありがとう、他の答えは良かったが、これはまさに私がやろうとしていたものです。 –

2

独自の関数を記述し、(適用)あなたのmyPairsループでそれを呼び出すようにしたいと思うような音:

yourfun <- function(pair){ 
    fm <- paste(pair, collapse='~') 
    coef <- lm(formula=fm, data=iris)$coefficients[2] 
    Spread <- iris[,pair[1]] - coef*iris[,pair[2]] 
    return(Spread) 
} 

次にこの関数を呼び出すことができます。

model <- apply(myPairs, 2, yourfun) 

私はこれがあると思います最もクリーンな方法。しかし、私はあなたが何をしたいのか分からないので、私はSpreadの例を作り上げていました。私の例では、Speciesという列が要因であるので、警告メッセージを受け取ることに注意してください。

+0

私はあなたがこれを不必要に複雑にしていると思います。まず、 'apply()'呼び出しを避けるために 'lapply()'を使うことができますが、より一般的には 'eval(parse())'ビットはおそらく名前付きベクトルで置き換え可能です。 – TARehman

+0

はい、ありがとう、私はいくつかの奇妙な問題(今解決した)を避けるためにちょうど迅速な回避策だったeval(parse())合併症を認識しています。私は答えを編集します。それはまだ有用かもしれません。 – jkt

1

いくつかのヒント:私は組み込み関数(modelformulaがあなたの元のバージョンで気になる)と同じ名前をつけてはいけません。

さらに、pasteを簡略化することができます。以下を参照してください。

最後に、より一般的な声明:何かをすべて*applyで実行する必要があるとは思わないでください。時には簡潔さと短いコードが実際に理解するのは難しいですが、*applyの機能は、ループを単純に超えても限界の速度向上を提供します。 (これはいつもRの場合ではありませんでしたが、それはこの時点です)。

# Get pairs 
myPairs <- combn(x = names(x = iris[1:4]),m = 2) 

# Just directly use paste() here 
myFormulas <- paste(myPairs[1,],myPairs[2,],sep = "~") 

# Store the models themselves into a list 
# This lets you go back to the models later if you need something else 
myModels <- lapply(X = myFormulas,FUN = lm,data = iris) 

# If you use sapply() and this simple function, you get back a named vector 
# This seems like it could be useful to what you want to do 
myCoeffs <- sapply(X = myModels,FUN = function (x) {return(x$coefficients[2])}) 

# Now, you can do this using vectorized operations 
iris[myPairs[1,]] - iris[myPairs[2,]] * myCoeffs[myPairs[2,]] 

私が正しく理解していれば、上記のことがうまくいくと思います。現在の出力の名前は無意味なので、あなた自身の設計の何か(それらはおそらくmyFormulasの値)で置き換える必要があることに注意してください。

+0

あなたは 'combn'の中でこれをすべて行うことができます:' fun < - function(x)coef(lm(paste(x、collapse = "〜")、data = iris))[2];コンボ(名前(アイリス[1:4])、2、楽しみ) ' – user20650

+0

興味深い、私はそれを知らなかった。簡潔さについて常に第3部に違反しているとは思われません。 – TARehman

関連する問題