2

For a given matrix A, how can i create a matrix B of the same size where every column is the mean (or any other function) of all the other columns?

example: a function on

A = [
     1     1     1
     2     3     4
     4     5     6]

should result in

B = [ 
      1   1  1 
      3.5 3 2.5
      5.5 5 4.5]
Divakar
  • 218,885
  • 19
  • 262
  • 358
fn.mat
  • 45
  • 3

3 Answers3

6

Perfect setup for bsxfun -

B = bsxfun(@minus,sum(A,2),A)./(size(A,2)-1)

Explanation: Breaking it down to two steps

Given

>> A
A =
     1     1     1
     2     3     4
     4     5     6

Step #1: For each element in A, calculate the sum of all elements except the element itself -

>> bsxfun(@minus,sum(A,2),A)
ans =
     2     2     2
     7     6     5
    11    10     9

Step #2: Divide each element result by the number of elements responsible for the summations, which would be the number of columns minus 1, i.e. (size(A,2)-1) -

>> bsxfun(@minus,sum(A,2),A)./(size(A,2)-1)
ans =
    1.0000    1.0000    1.0000
    3.5000    3.0000    2.5000
    5.5000    5.0000    4.5000
Divakar
  • 218,885
  • 19
  • 262
  • 358
4

Using your example:

[m,n]=size(A);
B=zeros(m,n);
for k=1:n
    B(:,k) = mean(A(:,[1:k-1 k+1:end]),2);
end

It may not be as quick or efficient as @Divakar's answer, but I tend to prefer for loop due to better readability. It might also make it easier to call a different function from mean.

am304
  • 13,758
  • 2
  • 22
  • 40
3

For an arbitrary function, you can use a vectorized approach if you don't mind using up more memory. Specifically, this requires generating a 3D array of size rxcxc, where r and c are the number of rows and columns of A.

f = @(x) prod(x,2); %// any function which operates on columns
c = size(A,2); %// number of columns
B = repmat(A, [1 1 c]);
B(:,1:c+1:end) = []; %// remove a different column in each 3D-layer
B = reshape(B, [], c-1, c); %// each 3D-layer of B contains a set of c-1 columns
result = f(B); %// apply function
result = squeeze(result); %// remove singleton dimension

As noted by Divakar in comments, anonymous functions tend to slow things down. It may be better to define the function f in a file.

Luis Mendo
  • 110,752
  • 13
  • 76
  • 147
  • 1
    Not sure if I have asked you this before, but here it - Do you think anonymous functions lead us to vectorized solutions? With what I have seen based on my little experience with them, they perform really slow, be it with `bsxfun` or `accumarray` and even just on their own. Any thoughts or insights? – Divakar Dec 03 '14 at 17:59
  • Good point. I also think they tend to be slow (I haven't tested really). The solution would still qualify as vectorized, because the function swallows the whole 3D array and produces (in a vectorized manner) the output. But I agree that if the result is slow, the purpose is defeated. A better approach would be to define `f` in a file – Luis Mendo Dec 03 '14 at 18:03
  • @Divakar A different matter would be calling `bsxfun` with an anonymous function (handle). That probably slows things down more; not (just) because of the function being anonymous, but because `bsxfun` probably works differently (internally) with an anonymous function than it does with one of its "built-ins" – Luis Mendo Dec 03 '14 at 18:08
  • @Divakar [This](http://stackoverflow.com/a/26219508/2586922) is what I meant (applied to `pdist` rather than `bsxfun`, but I think it's the same idea) – Luis Mendo Dec 03 '14 at 18:12
  • Agreed that `prod` must work in a vectorized manner here, so that's good there. Saving into a function file for more performance, agreed on that too based on my hunch, not really tested though. I think timing against the other loop based code could reveal something interesting here. – Divakar Dec 03 '14 at 18:25