Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Indexing a matrix using predetermined rule

I have a 72x3 double that looks like this

1   1   24  
1   1   125  
2   3   17  
6   2   54  
5   1   110  
4   4   55  
6   2   200
1   4   16  
3   3   87  
...  
6   2   63  

I would like to be able to find a value from column 3 based on the combination of values from column 1 and 2. For instance, let's call any value from column 1 m, value from column 2 n, and the corresponding value from column 3 p. If m=2, n=3, this will correspond to row 3 and thus p would be 17. If m=5, n=1, this will give us row 5 and thus b would be 110. Note that there will be cases where a set of m and n will give us two or more rows. An example would be m=1 and n1=1, which should yield 24 from the first row and 125 from the second row. In this case, the output should be [24 125]. Similarly, a combination and m=6 and n= 2 would give [54 200 63]. m ranges from 1 to 6 and n ranges from 1 to 4. Any combination of m and n would yield no more than 4 outputs. Could anyone help me with this indexing problem?

Thank you so much.

Alex

like image 916
A.Rainer Avatar asked Apr 07 '15 04:04

A.Rainer


3 Answers

One approach assuming A to be the input N x 3 array -

%// Find unique rows using the first two columns of A
[unqA12,~,idx] = unique(A(:,1:2),'rows')

%// Group elements from 3rd column of A based on the indexing pairs from
%// first coloumns of A and have these as a cell array
A3vals = accumarray(idx,A(:,3),[],@(x) {x})

%// Horizontally concatenate these results to present the final output
out = [num2cell(unqA12) A3vals]

Sample run on the given input yields the output as -

out = 
    [1]    [1]    [2x1 double]
    [1]    [4]    [        16]
    [2]    [3]    [        17]
    [3]    [3]    [        87]
    [4]    [4]    [        55]
    [5]    [1]    [       110]
    [6]    [2]    [3x1 double]

Or with arrayfun -

%// Find unique rows using the first two columns of A
[unqA12,~,idx] = unique(A(:,1:2),'rows')

%// Use arrayfun to do the groupings instead of accumarray this time 
out = [num2cell(unqA12) arrayfun(@(n) A(idx==n,3),1:max(idx),'Uni',0).']

Please note that the order of the third column elements won't be preserved in the first approach, but the second approach would do so.

like image 53
Divakar Avatar answered Oct 16 '22 10:10

Divakar


This wont be the fastest way, but another approach for beginners like me :)

in = [1   1   24; 
      1   1   125;
      2   3   17;
      6   2   54;  
      5   1   110;
      4   4   55;
      6   2   200;
      1   4   16;
      3   3   87];
m = input('Enter m ');
n = input('Enter n ');
Idx = all((cat(2,in(:,1) == m, in(:,2) == n)),2); 
out = in(:,3);
out1 = out(Idx);

Results:

Enter m 6
Enter n 2

ans =

    54
   200
----------------

Enter m 2
Enter n 3

ans =

    17
like image 37
Santhan Salai Avatar answered Oct 16 '22 11:10

Santhan Salai


If you only want the result for a given combination of m and n, you can use just indexing:

m = 6;
n = 2;
result = x(x(:,1)==m & x(:,2)==n, 3).';
like image 1
Luis Mendo Avatar answered Oct 16 '22 09:10

Luis Mendo