Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Given a matrix, we want to subtract the mean of each column, from all entries in that column. So given this matrix:

 (mat = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}}) // MatrixForm

Mathematica graphics

the mean of each column is m = Mean[mat].

Mathematica graphics

So the result should be

Mathematica graphics

This operation is called centering of observations in data science.

The best I could find using Mathematica, is as follows:

mat = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};
m = Mean[mat];
(mat[[All, #]] - m[[#]]) & /@ Range@Length@m // Transpose

But I am not too happy with it. I think it is too complicated. Is there a simpler way to do it? I tried Map and MapThread, but I had hard time getting the syntax to work.

In MATLAB, there is a nice function called bsxfun which is sort of like MapThread. Here is how it is done in MATLAB:

A=[1 2 3 4;5 6 7 8;9 10 11 12];
bsxfun(@minus,A,mean(A))

    -4    -4    -4    -4
     0     0     0     0
     4     4     4     4

It maps the function minus, taking one column from A and one element from mean(A). I think it is more clear than what I have in Mathematica. One should be able to do this in Mathematica using one of the map functions more easily and clearly than what I have above.

The question is: Can the Mathematica solution above be improved?

share|improve this question
up vote 14 down vote accepted
mat - ConstantArray[Mean[mat], 3]

or more generally:

mat - ConstantArray[Mean[mat], Length[mat]]
share|improve this answer

Well, transposing, subtracting, transposing...

Transpose[Transpose[mat] - Mean[mat]]
share|improve this answer

It is there:

Standardize[mat, Mean, 1 &]
share|improve this answer
    
Here comes the winner! – xzczd Jan 7 at 10:57
    
@xzczd Thanks. It may be not the fastest though, it rescales by 1 anyway. – Kuba Jan 7 at 11:39
    
Can use Identity' instead of 1&. – TheDoctor Jan 13 at 13:19
# - Mean@mat & /@ mat // MatrixForm

enter image description here

share|improve this answer
    
This computes the same Mean for each row - could be inefficient. – shrx Jan 8 at 9:29

If you don't mind the type of mat changes:

CircleMinus = Compile[{{a, _Real, 1}, {b, _Real, 1}}, a - b, RuntimeAttributes -> Listable]
mat⊖Mean@mat

$\left( \begin{array}{cccc} -4. & -4. & -4. & -4. \\ 0. & 0. & 0. & 0. \\ 4. & 4. & 4. & 4. \\ \end{array} \right)$

share|improve this answer
mat = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};
Transpose[Map[# - Mean[#] &, Transpose[mat]]]

which gives you

{{-4, -4, -4, -4}, {0, 0, 0, 0}, {4, 4, 4, 4}}
share|improve this answer

You might think of transposing your data. MATLAB naturally has the column as the basic subunit of the matrix, while Mathematica has the row.

Defining

(mat = Transpose[{{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 
 12}}]) // MatrixForm

the (transpose) of the desired result is then

mat - Mean /@ mat // MatrixForm
share|improve this answer

Here is something a bit closer to the Matlab syntax

mat1=Partition[Range@12,4];
mat2 = ConstantArray[Mean[mat1], Length[mat1]];
binaryFunction = #1 - #2 &;

MapThread[binaryFunction, {mat1,mat2}]
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.