Разделение столбцов по столбцам в R - PullRequest
19 голосов
/ 26 февраля 2012

Я пытаюсь масштабировать значения в матрице, чтобы каждый столбец складывался в единицу.Я пробовал:

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

, так что это работает, но мне кажется, что я что-то здесь упускаю.Это не может быть, как это обычно делается.Я уверен, что я глупый здесь.Будем благодарны за любую помощь, которую вы можете оказать, Дэви

Ответы [ 2 ]

45 голосов
/ 26 февраля 2012

См. ?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() только для этого конкретного случая

5 голосов
/ 26 февраля 2012

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

#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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...