Maddy
Maddy

Reputation: 2570

Calculate sum of certain rows (based on a uniqId) in a column without using for-loop in MATLAB

I have a matrix:

raw = [ 2001 1000 ; 2001 2000 ; 2001 1000 ; 2001 1000 ; 2001 2000 ; 5555 nan ; 5555 10000 ; 5555 20000 ; 5555 5000 ; 5555 20000 ; 5555 30000 ; 7777 1000 ; 7777 2000 ; 7777 3000 ; 7777 nan] ;

I need to find the sum of the every last 4 rows in Col2 (for each uniqId) based on the uniqIds which are in Col1. The Col2 might also have NaNs in them. The answer I want is:

[2001 nan; 2001 nan; 2001 nan; 2001 5000; 2001 6000; 5555 nan; 5555 nan; 5555 nan; 5555 nan; 5555 55000; 5555 75000; 7777 nan 7777 nan 7777 nan ; 7777 nan] ;

The raw matrix only has elements which have >= 4 rows of data. I CANNOT use a for-loop. Please help me with a vectorized form if possible. I can use a while loop if required.

Upvotes: 3

Views: 1661

Answers (2)

gnovice
gnovice

Reputation: 125854

You could do this using the functions UNIQUE and ACCUMARRAY. The following assumes that each group will have at least 4 elements. Any NaN values present in the raw data will result in a value of NaN for a summation window that includes that value:

[~,~,index] = unique(raw(:,1));  %# Get the indices for the unique values
sumFcn = @(x) {sum(hankel([nan(3,1); x(1:numel(x)-3)],...  %# Anonymous function
                          x(numel(x)-3:end)),2)};          %#   to get the sum
                                                           %#   over each window
                                                           %#   of four values
sumPerID = accumarray(index,raw(:,2),[],sumFcn);  %# Compute the windowed sum
                                                  %#   for each unique ID
raw(:,2) = vertcat(sumPerID{:})  %# Place the results back into the second
                                 %#   column of raw
raw =

        2001         NaN
        2001         NaN
        2001         NaN
        2001        5000
        2001        6000
        5555         NaN
        5555         NaN
        5555         NaN
        5555         NaN
        5555       55000
        5555       75000
        7777         NaN
        7777         NaN
        7777         NaN
        7777         NaN

Upvotes: 4

Simon
Simon

Reputation: 32883

Check out accumarray, that might help.

Upvotes: 0

Related Questions