Разделение столбцов на 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
так что это работает, но мне кажется, что я что-то пропустил. Это не может быть так, как это обычно делается. Я уверен, что я здесь глуп.
Любая помощь, которую вы можете дать, будет оценена по достоинству
Ура,
Дэви
Ответы
Ответ 1
См. ?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()
предназначен только для этого частного случая
Ответ 2
В обычном порядке у Джориса есть отличный ответ. Два других, которые приходят на ум:
#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