2012-02-25 2 views
15

Я пытаюсь масштабировать значения в матрице, чтобы каждый столбец добавлял до одного. Я пробовал:Разделение столбцов на colSums в 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

Brilliant. Спасибо! Стыдно, что я полностью забыл о «prop.table()». –

5

В обычном порядке у Джориса есть отличный ответ. Два других, которые пришли на ум:

#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),`/`) 

ответ JORIS' является самым быстрым на моей машине:

> 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 (масштаб (log (m), center = TRUE, scale = FALSE)) '(не очень хорошая идея по многим причинам!) –

+3

или 'scale (m, center = FALSE, scale = colSums (m))'. – flodel

Смежные вопросы