Doug
Doug

Reputation: 207

Finding unique values subject to a constraint - Matlab

I am trying to find unique values in one column of a matrix subject to the max amount listed in col 2 of the same matrix.

My code is the following:

    Testing = find(unique(RAW_DATA_2(:,1))&max(RAW_DATA_2(:,2)))

To me it reads find unique items in col 1 of the matrix which are also the max of col 2. Matlab disagrees with me however.

An alternative is to not even use the find function and just return a matrix with just the unique values and the max amount for each unique value which would be preferable. I have attempted to use some code I found here on Stack overflow to do this but am having issues with it since I cannot modify it from "first" to "unique".

 I = true(size(RAW_DATA_2,1),1);
 idx = [];
 while any(I)
     idx(end+1) = find(I,1,'first');  %#ok
     I = I & all(~bsxfun(@eq, RAW_DATA_2, RAW_DATA_2(idx(end),:)),2);
 end

 result = RAW_DATA_2(idx,:);

Upvotes: 2

Views: 102

Answers (3)

Divakar
Divakar

Reputation: 221574

It seems an accumarray based solution might also be a good fit here -

%// Find unique elements from column-1 and also tag/ID each of its elements
[col1_unq,~,id] = unique(RAW_DATA_2(:,1),'stable');

%// Get the max from second column based on the IDs and then concatenate
%// with unique rows from column-1 for the final output
result = [col1_unq accumarray(id,RAW_DATA_2(:,2),[],@max)]

Sample run -

RAW_DATA_2 =
   12.5000    5.0000
   12.5000    2.5000
    5.0000   12.5000
   10.0000   10.0000
    7.5000    7.5000
    7.5000   10.0000
   12.5000    7.5000
    5.0000   10.0000
result =
   12.5000    7.5000
    5.0000   12.5000
   10.0000   10.0000
    7.5000   10.0000

Upvotes: 1

gdvd
gdvd

Reputation: 56

I think your clarifying comment makes the question a lot more understandable. You should consider adding it to the question itself. Here's some code that may help you

a = [0 10; 1 100; 3 175; 4 80; 1 200; 2 400; 3 150; 0 10]; % your raw data
asorted = unique(a, 'rows');  %returns unique rows, sorted by value

Note that asorted does not contain any duplicate rows and is sorted in the following way:

asorted =
 0    10
 1   100
 1   200
 2   150
 2   300
 2   400
 3   150
 3   175
 4    80

It is now clear that the lowermost row containing each unique element of column 1 is what we need. This can be accomplished as follows:

diffidx = [diff(asorted(:, 1)); 1];  % appending 1 because the last row 
                                     % must always be included
result = asort(diffidx~=0, :)

Upvotes: 2

eigenchris
eigenchris

Reputation: 5821

This will work, but it might be a bit excessive if you have a lot of unique dates.

m = max( bsxfun(@times, A(:,2), bsxfun(@eq,unique(A(:,1))',A(:,1)) ));
answer = [unique(A(:,1)), m']

As an example with 4 dates, 1,2,3,4:

 2    65
 2    16
 3    94
 4    25
 3    63
 4    26
 3    50
 4    82
 1    92
 3    16
 1    49
 1   100
 2    62
 1    44
 3    34

My output is the following, with the "dates" on the left and their corresponding maxima on the right.

 1   100
 2    65
 3    94
 4    82

Upvotes: 1

Related Questions