# Best way to emulate MATLAB's bsxfun using Map and similar functions

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


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

So the result should be

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?

-

mat - ConstantArray[Mean[mat], 3]


or more generally:

mat - ConstantArray[Mean[mat], Length[mat]]

-

Well, transposing, subtracting, transposing...

Transpose[Transpose[mat] - Mean[mat]]

-

It is there:

Standardize[mat, Mean, 1 &]

-
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


-
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)$

-
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}}

-

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

-

Here is something a bit closer to the Matlab syntax

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