0

I have a matrix m (conisting of three columns, each consisting of integers and having a mean of 5,10, and 15 respectively):

m <- round(matrix(data=cbind(rnorm(30, 5), rnorm(30, 10), rnorm(30, 15)), nrow=30, ncol=3), 0)

Now, I would like to have a matrix of the same dimensions as m, where each value x is calculated as x minus the mean of the column in which x is found. How can this be done? I have tried applying various apply-functions (specifically, I have been looking at two questions by user3640617 and User60), but the problem seems to be that I can't use the mean of a row as an argument in sapply, lapply or vapply...

Example: If the head(m) is

     [,1] [,2] [,3]
[1,]    6   11   14
[2,]    6    8   16
[3,]    6   11   15
[4,]    6   10   17
[5,]    5    9   15
[6,]    3   10   15

I want to get

     [,1] [,2] [,3]
[1,]    1    1   -1
[2,]    1   -2    1
[3,]    1    1    0
[4,]    1    0    2
[5,]    0   -1    0
[6,]   -2    0    0
Lukas
  • 424
  • 3
  • 6
  • 17

2 Answers2

5

One way is to use apply(m, 2, function(x)(x-mean(x)))

Another way is to use t(t(m)-colMeans(m))

VicaYang
  • 544
  • 3
  • 17
  • Just for the beginners (like me): the copy-paste-variante would be `apply(m, 2, function(x)(x-mean(x)))` – Lukas Jul 03 '18 at 08:57
  • 1
    Note that the vectorized solution using `colMeans` is ~ 200 times faster than `apply` in a benchmark with a 200x50 matrix. Always try to use vectorized operations with R! – LAP Jul 03 '18 at 09:03
  • 1
    Yes, so I add a vectorized solution. I post the 'apply' because he asked for an "apply" solution. BTW, any suggestion for changing the broadcast direction when using vectorized operations? (I hate to transpose the matrix twice) – VicaYang Jul 03 '18 at 09:06
  • 1
    @VicaYang I did not want to criticise your answer, I just wanted to point out to Lukas that the vectorized solution is much faster :) – LAP Jul 03 '18 at 09:14
4

you are looking for

scale(m,center=T,scale=F)[,]

another way is

sweep(m,2,colMeans(m)) 

but not as fast as the scale

Onyambu
  • 67,392
  • 3
  • 24
  • 53