HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

Extract the largest value for each day from a matrix

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
theeachvaluelargestforextractfrommatrixday

Problem

I have a matrix in which the right-most elements are repeated YYYYMMDD dates in descending order, for example:

40        1122        1711    20160326
 169         700         950    20160326
  40        1630        1711    20160326
 182         700         950    20160327
  40        1029        1711    20160327
 169         700         950    20160327
  40        1630        1711    20160327
 122         700         950    20160328
  40        1630        1711    20160328
 169         700         950    20160328
  40        1630        1711    20160328
3049         700         950    20160331
  40        1630        1711    20160331
3049         700         950    20160331
  40        1630        1711    20160331
 169         700         950    20160401
  40        1630        1711    20160401
 169         700         950    20160401
  40        1630        1711    20160401


Within each date, I want to keep only the row that corresponds to the largest element in the leftmost column. So I would like to produce a new matrix:

169         700         950    20160326
 182         700         950    20160327
 169         700         950    20160328
3049         700         950    20160331
 169         700         950    20160401


The code I have now is:

idx1 = find([1;diff(A(:,4))]);
idx2 = find([diff(A(:,4));1]);
B = zeros(length(idx1),4);
for ii = 1:length(idx1)
    row_number = find(A(idx1(ii):idx2(ii),1) == max(A(idx1(ii):idx2(ii),1)),1);
    B(ii,:) = A(idx1(ii)+row_number-1,:);
end


Are there ways to improve this code? I'm looking for coding conventions, improve performance, possible vectorization etc.

Solution

A few notes: (I implemented this in Octave, so there may be differences between my code and a proper Matlab implementation, but there shouldn't be).

-
First we care about only unique dates, right? So lets grab
indices for their groupings. I'm assuming this original data is
stored in the matrix A.

[X, y, z] = unique(A(:, 4))


Now z is the only value I used from this output, so you could
ignore the other returns by putting ~ in their place.

-
Second, let's split out data up based on these groups. We can use
the function accumarray() to accomplish this nicely. If we
pass in the function handle @max to it, it'll even find the max
within these groups.

B = accumarray(z, A(:, 1), [], @max)


There is some trick to get each row corresponding to that maximum value based on the z parameter, but after investigating this for a few hours I still haven't figured it out and have given up. You could try using find() to get these rows instead, using z to make sure we are grabbing the right values.

Code Snippets

[X, y, z] = unique(A(:, 4))
B = accumarray(z, A(:, 1), [], @max)

Context

StackExchange Code Review Q#133465, answer score: 4

Revisions (0)

No revisions yet.