2010-11-21 7 views
85

行列が2であり、その引数の1つとして2ベクトルをとる関数があるとします。行列の各行に関数を適用し、nベクトルを取得したいと思います。どのようにRでこれを行うには?例えば行列またはデータフレームのすべての行に関数を適用する

、私は3点で2D標準正規分布の密度を計算したい:

bivariate.density(x = c(0, 0), mu = c(0, 0), sigma = c(1, 1), rho = 0){ 
    exp(-1/(2*(1-rho^2))*(x[1]^2/sigma[1]^2+x[2]^2/sigma[2]^2-2*rho*x[1]*x[2]/(sigma[1]*sigma[2]))) * 1/(2*pi*sigma[1]*sigma[2]*sqrt(1-rho^2)) 
} 

out <- rbind(c(1, 2), c(3, 4), c(5, 6)) 

方法outの各行に関数を適用しますか?

指定した方法で、関数のポイント以外の他の引数の値を渡す方法はありますか?

答えて

136

あなたは、単にapply()関数を使用する:

R> M <- matrix(1:6, nrow=3, byrow=TRUE) 
R> M 
    [,1] [,2] 
[1,] 1 2 
[2,] 3 4 
[3,] 5 6 
R> apply(M, 1, function(x) 2*x[1]+x[2]) 
[1] 4 10 16 
R> 

これはマトリックスを取り、各行に(愚かな)関数を適用します。関数に余分な引数を4番目、5番目、...の引数としてapply()に渡します。

+0

おかげで使用されているかを注意深く見てください結果を見てみましょう!行列の行が関数の最初の引数でない場合はどうなりますか?行列の各行に割り当てられている関数のargを指定する方法は? – Tim

+0

'apply()'のヘルプを読む - 行ごとに(2番目の引数が1、それ以外の場合)、現在の行(またはcol)が常に最初の引数です。それが物事を定義する方法です。 –

+0

@Tim:内部R関数を使用し、その行が最初のargでない場合は、Dirkが行ったようにして、行**が最初のargである独自のカスタム関数を作成します。 –

6

最初のステップでは、関数オブジェクトを作成してから適用します。あなたが同じ行数を持つ行列オブジェクトが必要な場合は、それを事前に定義することができますし、(そうでない場合、戻り値がベクトルに簡素化されます)示すように、オブジェクト[]の形式を使用します。

bvnormdens <- function(x=c(0,0),mu=c(0,0), sigma=c(1,1), rho=0){ 
    exp(-1/(2*(1-rho^2))*(x[1]^2/sigma[1]^2+ 
          x[2]^2/sigma[2]^2- 
          2*rho*x[1]*x[2]/(sigma[1]*sigma[2]))) * 
    1/(2*pi*sigma[1]*sigma[2]*sqrt(1-rho^2)) 
    } 
out=rbind(c(1,2),c(3,4),c(5,6)); 

bvout<-matrix(NA, ncol=1, nrow=3) 
bvout[] <-apply(out, 1, bvnormdens) 
bvout 
      [,1] 
[1,] 1.306423e-02 
[2,] 5.931153e-07 
[3,] 9.033134e-15 

あなたが望んでいた場合その後、呼び出しは関数の後に名前付き引数を含める必要があり、あなたのデフォルトパラメータ以外を使用する:

bvout[] <-apply(out, 1, FUN=bvnormdens, mu=c(-1,1), rho=0.6) 

は、(適用)より高次元の配列でも使用することができ、MARGIN引数がベクトルと同様に、単一の整数を指定できます。 。

14

合計や平均などの一般的な機能を適用する場合は、apply(data, 1, sum)よりも速いため、rowSumsまたはrowMeansを使用する必要があります。それ以外の場合は、apply(data, 1, fun)を付けます。 (ディルクがすでに示唆したように)あなたはFUNの引数の後に追加の引数を渡すことができます。

set.seed(1) 
m <- matrix(round(runif(20, 1, 5)), ncol=4) 
diag(m) <- NA 
m 
    [,1] [,2] [,3] [,4] 
[1,] NA 5 2 3 
[2,] 2 NA 2 4 
[3,] 3 4 NA 5 
[4,] 5 4 3 NA 
[5,] 2 1 4 4 

は、その後、あなたがこのような何かを行うことができます。

apply(m, 1, quantile, probs=c(.25,.5, .75), na.rm=TRUE) 
    [,1] [,2] [,3] [,4] [,5] 
25% 2.5 2 3.5 3.5 1.75 
50% 3.0 2 4.0 4.0 3.00 
75% 4.0 3 4.5 4.5 4.00 
2

あなたがデータセットのさまざまな部分を使用する場合は別のアプローチ単一の値の代わりにrollapply(data, width, FUN, ...)を使用することです。幅のベクトルを使用すると、データセットのさまざまなウィンドウに関数を適用できます。私はこれを非常に効率的ではありませんが、適応フィルタリングルーチンを構築するために使用しました。

11

ここでは、行列の各行に関数を適用する簡単な例を示します。 (ここで、関数が適用1にすべての行を正規化)

注:apply()からの結果はなければならなかったが、入力行列Aと同じレイアウトを得るためt()を用いを転置しました。

A <- matrix(c(
    0, 1, 1, 2, 
    0, 0, 1, 3, 
    0, 0, 1, 3 
), nrow = 3, byrow = TRUE) 

t(apply(A, 1, function(x) x/sum(x))) 

結果:

 [,1] [,2] [,3] [,4] 
[1,] 0 0.25 0.25 0.50 
[2,] 0 0.00 0.25 0.75 
[3,] 0 0.00 0.25 0.75 
3

はよく仕事をして適用しますが、非常に遅いです。 sapplyとvapplyを使用すると便利です。 dplyrの行方向も有用です どのデータフレームの列に従った製品を行う方法の例を見てみましょう。

vapply/sapply/applyを使用する前に変数に代入すると、多くの時間が短縮されるので、良い方法です。のは、マイクロベンチマークは

a = data.frame(t(iris[1:10,1:3])) 
b = iris[1:10,1:3] 
microbenchmark::microbenchmark(
    apply(b, 1 , prod), 
    vapply(a, prod, 0), 
    sapply(a, prod) , 
    apply(iris[1:10,1:3], 1 , prod), 
    vapply(data.frame(t(iris[1:10,1:3])), prod, 0), 
    sapply(data.frame(t(iris[1:10,1:3])), prod) , 
    b %>% rowwise() %>% 
     summarise(p = prod(Sepal.Length,Sepal.Width,Petal.Length)) 
) 

tは()

関連する問題