2012-02-25 10 views
15

各列が1つになるように、行列の値を拡大縮小しようとしています。私は試した:colSumで列を分割するR

m = matrix(c(1:9),nrow=3, ncol=3, byrow=T) 
    [,1] [,2] [,3] 
[1,] 1 2 3 
[2,] 4 5 6 
[3,] 7 8 9 

colSums(m) 
12 15 18 

m = m/colSums(m) 
      [,1]  [,2] [,3] 
[1,] 0.08333333 0.1666667 0.25 
[2,] 0.26666667 0.3333333 0.40 
[3,] 0.38888889 0.4444444 0.50 

colSums(m) 
[1] 0.7388889 0.9444444 1.1500000 

これは明らかにこれは動作しません。 は、私は、この試みた:

m = m/matrix(rep(colSums(m),3), nrow=3, ncol=3, byrow=T) 
      [,1]  [,2]  [,3] 
[1,] 0.08333333 0.1333333 0.1666667 
[2,] 0.33333333 0.3333333 0.3333333 
[3,] 0.58333333 0.5333333 0.5000000 

m = colSums(m) 
[1] 1 1 1 

をので、これは動作しますが、私はここで何かが欠けてるようには感じています。これは日常的に行われる方法ではありません。私はここで馬鹿だと確信しています。 あなたが与えることができるすべてのヘルプは 乾杯、 デイビー

答えて

38

をいただければ幸いです?sweep、例えばを参照してください。

> sweep(m,2,colSums(m),`/`) 
      [,1]  [,2]  [,3] 
[1,] 0.08333333 0.1333333 0.1666667 
[2,] 0.33333333 0.3333333 0.3333333 
[3,] 0.58333333 0.5333333 0.5000000 

か、行列を転置することができ、その後colSums(m)が正しく再生されます。このように、その後再び転置することを忘れないでください:

> t(t(m)/colSums(m)) 
      [,1]  [,2]  [,3] 
[1,] 0.08333333 0.1333333 0.1666667 
[2,] 0.33333333 0.3333333 0.3333333 
[3,] 0.58333333 0.5333333 0.5000000 

それとも、基本的には同じことをする機能prop.table()を使用します。

> prop.table(m,2) 
      [,1]  [,2]  [,3] 
[1,] 0.08333333 0.1333333 0.1666667 
[2,] 0.33333333 0.3333333 0.3333333 
[3,] 0.58333333 0.5333333 0.5000000 

時間差はかなり小さいです。 sweep()の機能とt()のトリックが最も柔軟な解決策です。prop.table()はこの特定のケースのみです

+0

ブリリアント。ありがとうございました!私は 'prop.table()'を完全に忘れてしまったことを恥ずかしく思っていました。 –

5

通常、Jorisは素晴らしい答えがあります。頭に浮かんだ二つの他人:

#Essentially your answer 
f1 <- function() m/rep(colSums(m), each = nrow(m)) 
#Two calls to transpose 
f2 <- function() t(t(m)/colSums(m)) 
#Joris 
f3 <- function() sweep(m,2,colSums(m),`/`) 

ヨリス答えは、私のマシン上で最速です:

> m <- matrix(rnorm(1e7), ncol = 10000) 
> library(rbenchmark) 
> benchmark(f1,f2,f3, replications=1e5, order = "relative") 
    test replications elapsed relative user.self sys.self user.child sys.child 
3 f3  100000 0.386 1.0000  0.385 0.001   0   0 
1 f1  100000 0.421 1.0907  0.382 0.002   0   0 
2 f2  100000 0.465 1.2047  0.386 0.003   0   0 
+1

あなたの投稿のように見え、私の編集はお互いに合格しました。賛辞のためのThx。 –

+0

あなたが巨大なデータセットで作業しているのでなければ、私はその表現力のために 'sweep'が好きです...ちょっと魅力的で、exp(scale(log(m)、center = TRUE、scale = FALSE)多くの理由で良い考えではありません!) –

+3

または 'scale(m、center = FALSE、scale = colSums(m))'です。 – flodel