cumsum within a group
    3 Ansichten (letzte 30 Tage)
  
       Ältere Kommentare anzeigen
    
Hi, Is there a faster way to do a cumulative sum within a group? data looks like
    year val cumval
data=[1  10  10;
1  10  20;
1  10  30;
1  10  40;
2  10  10;
2  15  25;
2  20  45;
3  5  5;
4  10  10];
As you see cumVal is sumsum within a year only. Then what I want to do is to compute a new val that reflects this yearly cap. I create 2 more columns. cumval_w_annualCap reflects the annual cap value of 25 in this example. The val_cap is the re-compute val that reflects
cumval_w_annualCap val_cap
tcumsum=[10  10;
20  10;
25  5;
25  0;
10  10;
25  15;
25  0;
5  5;
10  10];
How I compute it seems to be very slow.
val_cap= data( :,2);
yearlyLim=25;
[ uniqYrs, indxYr] = unique( data(:,1));
nUniqYr = length(uniqYrs);
for runYr= 1: nUniqYr
    if runYr< nUniqYr
        tindx= [indxYr( runYr):indxYr( runYr+1)-1];
    else
        tindx= [indxYr( runYr):length( data(:,2))];
    end % 
    yrVal   = data(tindx,2);
    tcumval= cumsum( yrVal, 1);
    indxAggCap = find(tcumval >= yearlyLim, 1);
      if indxAggCap == 1
          yrVal( indxAggCap)= yearlyLim;
      else
          yrVal( indxAggCap)= yearlyLim - tcumval( indxAggCap-1);
      end % if indxAggCap
      yrVal( indxAggCap+1:end)= 0;
      val_cap( tindx)= yrVal;
end %
Anyway to vectorize this algorithm?
Thanks,
0 Kommentare
Antworten (2)
  Thorsten
      
      
 am 22 Jun. 2016
        
      Bearbeitet: Thorsten
      
      
 am 22 Jun. 2016
  
       data=[1  10  10;
1  10  20;
1  10  30;
1  10  40;
2  10  10;
2  15  25;
2  20  45;
3  5  5;
4  10  10];
  % first column of tcumsum
 yearlyLim=25;
 t1 = data(:,3);
 t1(t1 > yearlyLim) = yearlyLim;
 % second column of tcumsum
 [~, b] = unique(data(:,1));
 Nb = numel(b);
 t2 = arrayfun(@(i)  [t1(b(i)); diff(t1(b(i):b(min(i+1, Nb))-1))]', 1:Nb, 'Uni', 0);
 t2 = cell2mat(t2)';
 tcumsum = [t1 t2];
Since R2015b you can use split apply
t2 = cell2mat(splitapply(@(x) {[x(1); diff(x)]}, t1, data(:,1)));
0 Kommentare
  Andrei Bobrov
      
      
 am 22 Jun. 2016
        data=[1  10 
1  10 
1  10 
1  10 
2  10 
2  15 
2  20 
3  5 
4  10];
[~,~,c] = unique(data(:,1));
d = data(:,2);
o1 = cell2mat(accumarray(c,d,[],@(x){cumsum(x)}))
val_cap = cell2mat(accumarray(c,min(o1,25),[],@(x){[x(1);diff(x)]}));
0 Kommentare
Siehe auch
Kategorien
				Mehr zu Electrical Block Libraries finden Sie in Help Center und File Exchange
			
	Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!