3

I have a 12-D array and am using each dimension as an index value in an optimization problem.

A(:,:,i1,i2,i3,i4,i5,i6,i7,i8,i9,i10)

each index value i is a value from 1 to 5.

I want to sort A from greatest to least and keep track of the indices so I know which indices correspond to to what value of A.

So my ideal output would be a 2 column cell/array with one column being the value and the other other column being the index values.

For a simple 3D example: say I have a 3D array: A(:,:,i1).

Where:

A(:,:,1) =  2 
A(:,:,2) =  6 
A(:,:,3) =  13 
A(:,:,4) =  11 
A(:,:,5) =  5  

I would like my output to be:

13   3
11   4
6    2
5    5
2    1

EDIT:

assume I have 1x1x3x3 sized input such that

A(1,1,1,1) = 3

A(1,1,2,1) = 1

A(1,1,3,1) = 23

A(1,1,1,2) = 12

A(1,1,2,2) = 9

A(1,1,3,2) = 8

A(1,1,1,3) = 33

A(1,1,2,3) = 14

A(1,1,3,3) = 6

the expected output would be:

33  [1,1,1,3]

23  [1,1,3,1]

14  [1,1,2,3]

12  [1,1,1,2]

9  [1,1,2,2]

8  [1,1,3,2]

6 [1,1,3,3]

3  [1,1,1,1]

1  [1,1,2,1]

Joe
  • 457
  • 5
  • 18
Oliver Oliver
  • 2,057
  • 4
  • 16
  • 14

2 Answers2

2

This should be a generic code for any multi-dimensional input array -

%// Sort A and get the indices
[sorted_vals,sorted_idx] = sort(A(:),'descend'); 

%// Set storage for indices as a cell array and then store sorted indices into it
c = cell([1 numel(size(A))]); 
[c{:}] = ind2sub(size(A),sorted_idx);

%// Convert c to the requested format and concatenate with cell arary version of 
%// sorted values for the desired output
out = [num2cell(sorted_vals) mat2cell([c{:}],ones(1,numel(A)),numel(size(A)))]; 

The generic code owes its gratitude to this fine solution.

Community
  • 1
  • 1
Divakar
  • 218,885
  • 19
  • 262
  • 358
  • well that's the same problem for me. Is there any way we can make this code work for variable dimensionality? Since you also have to specify `[p1,...,p12]` – Autonomous Oct 30 '14 at 20:39
  • @Divakar Thanks so much this works perfectly!! Now I just to to figure out a way to visualize/display this data. – Oliver Oliver Oct 30 '14 at 20:45
  • @OliverOliver isn't the cell used to display your data, for example, in my answer, the cell `yourCell`? – Autonomous Oct 30 '14 at 20:49
  • @Parag S. Chandakkar Yes, it is. I was was just thinking out loud. My next step is to display this output in a plot or something to make it super easy to visualize. – Oliver Oliver Oct 30 '14 at 20:53
  • 1
    @ParagS.Chandakkar Check out the edits on how to make it generic. – Divakar Oct 30 '14 at 20:56
  • @OliverOliver So that `out` would be used to get your plot I am assuming? – Divakar Oct 30 '14 at 20:56
  • @OliverOliver Also, check out the edits, as the code is now less "stretchy", compact and generic! Let us know how it goes with you? – Divakar Oct 30 '14 at 21:00
1

I guess this is what you want:

b=A(:);
[sorted_b,ind]=sort(b,'descend');
[dim1,dim2,dim3,dim4]=ind2sub(size(A),ind);

%arranging in the form you want
yourCell=cell(size(b,1),2);
yourCell(:,1)=mat2cell(sorted_b,ones(size(b,1),1),1);

%arranging indices -> maybe vectorized way is there for putting values in "yourCell"
for i=1:size(b,1)
    yourCell{i,2}=[dim1(i) dim2(i) dim3(i) dim4(i)];
end

For the array A, given by you, my output looks like:

33  [1,1,1,3]
23  [1,1,3,1]
14  [1,1,2,3]
12  [1,1,1,2]
9   [1,1,2,2]
8   [1,1,3,2]
6   [1,1,3,3]
3   [1,1,1,1]
1   [1,1,2,1]

which matches with your output.

Autonomous
  • 8,935
  • 1
  • 38
  • 77
  • Something does't work when trying to extract the indices back out. I i get this for [3,3,12,2420] for the indices output when trying a 11-D array – Oliver Oliver Oct 30 '14 at 20:12
  • tell exact size of your matrix, as in `m x n x p x...` – Autonomous Oct 30 '14 at 20:20
  • [1 x 1 x 4 x 4 x 4 x 4 x 4 x 4 x 4 x 4 x 4] – Oliver Oliver Oct 30 '14 at 20:26
  • Now I understand, well my code works, but it requires that you specify as many no. of variables as your matrix dimensionality i.e. if your matrix is 4-D. Then you should change `[row,col,layer]=ind2sub(size(a),ind);` to `[dim1,dim2,dim3,dim4]=ind2sub(size(a),ind);` and change `yourCell{i,2}=[row(i) col(i) layer(i)];` to `yourCell{i,2}=[dim1(i) dim2(i) dim3(i) dim4(i)];`. So my code will not work, if you enter variable dimensionality arrays i.e. 12-D, 11-D etc. See the modified code. It works for a 4-D array and it will work for an 11-D array if you write `[dim1,dim2,...,dim11]` as I suggested. – Autonomous Oct 30 '14 at 20:32
  • +1 for you too already and you can use the generic-part if you need to. It's not really an essential part of my code. – Divakar Oct 30 '14 at 21:20
  • ya I know... our solutions are very similar, I just didn't have time to make it generic, nice job. @OliverOliver Please consider accepting the appropriate solution. – Autonomous Oct 30 '14 at 21:35
  • Comeon I skipped loops! :) – Divakar Oct 30 '14 at 21:37
  • ya, I didn't pay attention in optimizing that... I even wrote it in solution that "maybe vectorized way is there for putting values in "yourCell"" – Autonomous Oct 30 '14 at 21:38