2

Suppose A is a 3-D matrix as below (2 rows-2 columns-2 pages).

A(:,:,1)=[1,2;3,4];
A(:,:,2)=[5,6;7,8];

I want to have a vector, say "a", whose inputs are the average of diagonal elements of matrices on each page. So in this simple case, a=[(1+4)/2;(5+8)/2].

But I have difficulties in matlab to do so. I tried the codes below but failed.

mean(A(1,1,:),A(2,2,:))
Luis Mendo
  • 110,752
  • 13
  • 76
  • 147
Jie Wei
  • 191
  • 9

2 Answers2

2

You can use bsxfun for a generic solution -

[m,n,r] = size(A)
mean(A(bsxfun(@plus,[1:n+1:n^2]',[0:r-1]*m*n)),1)

Sample run -

>> A
A(:,:,1) =
     8     4     1
     7     6     3
     1     5     8
A(:,:,2) =
     1     7     6
     8     5     2
     1     2     7
A(:,:,3) =
     6     2     8
     1     1     6
     1     4     5
A(:,:,4) =
     8     1     6
     1     5     1
     9     2     7
>> [m,n,r] = size(A);
>> sum(A(bsxfun(@plus,[1:n+1:n^2]',[0:r-1]*m*n)),1)
ans =
    22    13    12    20
>> mean(A(bsxfun(@plus,[1:n+1:n^2]',[0:r-1]*m*n)),1)
ans =
       7.3333       4.3333            4       6.6667
Divakar
  • 218,885
  • 19
  • 262
  • 358
2

You can use "partially linear indexing" in the two dimensions that define the diagonal, as follows:

  1. Since partially linear indexing can only be applied on trailing dimensions, you first need to apply permute to rearrange dimensions, so that the first and second dimensions become second and third.
  2. Now you leave the first dimension untouched, linearly-index the diagonals in the second and third dimensions (which effectly reduces those two dimensions to one), and apply mean along the (combined) second dimension.

Code:

B = permute(A, [3 1 2]);                                   %// step 1: permute
result = mean(B(:,1:size(A,1)+1:size(A,1)*size(A,2)), 2);  %// step 2: index and mean

In your example,

A(:,:,1)=[1,2;3,4];
A(:,:,2)=[5,6;7,8];

this gives

result =
    2.5000
    6.5000
Community
  • 1
  • 1
Luis Mendo
  • 110,752
  • 13
  • 76
  • 147
  • I was playing out this partial linear indexing thing and that's what seemed like the key with it - `partially linear indexing can only be applied on trailing dimensions`. Just need to explore more about it I guess. – Divakar Sep 10 '15 at 12:01
  • @Divakar Yes, that's the key. So you need `permute` to make those dimensions the last. Then you can use (partially) linear indexing over any desired number of trailing dimensions – Luis Mendo Sep 10 '15 at 12:05
  • 1
    Ah yes nice trick! So, after doing the computations, one needs to permute back to original dimensions, right? If there is reduction, like in this question, that might not be needed, but in a generic case, permuting back might be needed, right? – Divakar Sep 10 '15 at 12:08
  • @Divakar Yes, in general you would need that. However, partially linear indexing reduces the _n_ last dimensions to one. So when permuting "back" that should be taken into accout – Luis Mendo Sep 10 '15 at 12:11
  • Oh yes, that's saving it there, unless I am dealing with lets say 4D or 5D cases? I guess in those cases, the permuting back needs to accommodate for the "merging" that partially indexing did. – Divakar Sep 10 '15 at 12:14
  • 1
    Say you have a 4D array. If you linearly-index the trailing 2 dimensions, you have reduced those 2 dimensions to 1, and so you have reduced the 4D array to 3D. Therefore you would permute (back?) a 3D array, not a 4D array. You could perhaps un-merge the merged dimensions back into 2, but that would require `reshape` after the `permute` – Luis Mendo Sep 10 '15 at 12:34