Reputation: 2570
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
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