Cumulative sum by group
    조회 수: 7 (최근 30일)
  
       이전 댓글 표시
    
Hi, Could someone explain how to compute the running sum by group (without using for loop)? A example is: groupid = [1; 1; 1; 2; 2; 3; 3;]; value=[1;2;3;4;5;6;7]. the desired result is: runsum = [1;3;6; 4;9; 6;13]. Thanks a lot. zppine
댓글 수: 0
답변 (4개)
  Sean de Wolski
      
      
 2012년 7월 27일
        
      편집: Sean de Wolski
      
      
 2012년 7월 27일
  
      Using a for-loop here may be your best option. However, my unconditional love for accumarray forces me to present you with this:
groupid = [1; 1; 1; 2; 2; 3; 3;]; 
value=[1;2;3;4;5;6;7]; 
gcs = cell2mat(accumarray(groupid,value,[],@(x){cumsum(x)}))
댓글 수: 0
  Daniel
 2015년 7월 3일
        function S = labeledCumsum(X,L)
% e.g. X=[3   5 8  9 1  2    5    8 5  4  9   2]
%      L=[0   1 1  2 2  0    0    1 1  1  0   5]
% result=[NaN 5 13 9 10 NaN  NaN  8 13 17 NaN 2]
L = L(:);
X = X(:);
if numel(L) ~= numel(X)
    error('The two inputs should be vectors of the same length.')
end
% Do the full cumulative sum
X(isnan(X)) = 0;
S = cumsum(X);
mask = logical(L);
% Lookup the cumulative value just before the start of each segment
isStart = mask & [true ; L(1:end-1) ~= L(2:end)];
startInds = find(isStart);
if startInds(1) == 1
    S_starts = [0 ; S(startInds(2:end)-1)];
else
    S_starts = S(startInds-1);
end
% Subtract off the excess values (i.e. the ones obtained above)
L_safe = cumsum(isStart); % we do this to main case the labels in L were not sorted integers
S(mask) = S(mask) - S_starts(L_safe(mask));
% Put NaNs in the false blocks
S(L==0) = NaN; 
end
댓글 수: 0
  Quoc T. Phan
 2020년 6월 19일
        Hello
When it comes to work with group, these two functions are great tools. They go together
- findgroups: --> indexing groups
 - splitapply: --> split your data by index, then apply @function to it, then combine back to original
 
Here is a sample code
clear
load patients
% Create a table X
X = table(LastName,Gender,Height,Weight,Age)
% Sort rows by Gender and Last Name (Actually u dont need Last Name, but I
% just put here in case)
X =  sortrows(X,{'Gender' 'LastName'},{'ascend' 'ascend'})
% Function 01: Using findgroups --> to return logical index
G = findgroups(X.Gender) 
% (*) Note: by default they index by alphabet order. Although 1st obs is male,
% however, F(emale) is before M(ale). Then 1 is Female and 2 is Male.
% Function 02: Using splitapply
% Basically what it does it slit table X by logical index G
% It then apply function cumsum for variable X.Height
cumHeight = splitapply(@(x1){cumsum(x1)},X.Height,G)
% Change cell to matrix and add to table X
X.cumHeight = cell2mat(cumHeight)
댓글 수: 0
참고 항목
카테고리
				Help Center 및 File Exchange에서 Operators and Elementary Operations에 대해 자세히 알아보기
			
	Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!