You mean, something like this?
data have;
input Id $ date :date9. cb;
format date date5.;
datalines;
X 1jan2019 27
Y 1jan2019 47
X 2jan2019 10
Y 2jan2019 13
X 3jan2019 37
;
proc sort data=have; by id date; run;
%let limit=50;
data want;
s = 0;
do until(last.id);
set have; by id;
cb2 = max(0, min(cb, &limit. - s));
s = s + cb;
output;
end;
drop s;
run;
proc sort data=want; by date id; run;
proc print data=want noobs; run;
I think I understand that new variable CB2 should never exceed 50, but I don't understand any other rule you have in mind for CB2.
What are your rules of constructing CB2?
OK, I get it now. For each ID, you want to maintain a cumulative sum of CB. As long as the sum is <= 50, CB2=CB. But if it exceeds 50, then CB2 is the value that brings the sum to exactly 50.
If your data were sorted by ID/DATE, you could just keep a cumulative sum (CBSUM) to guide your assignment of CB2.Then resort to original order (by DATE/ID):
data have;
input Id $ date date9. cb;
format date date9.;
datalines;
X 1jan2018 27
Y 1jan2018 47
X 2jan2018 10
Y 2jan2018 13
X 3jan2018 37
Y 3jan2018 11
run;
proc sort data=have;
by id date;
run;
data want (drop=cbsum);
set have;
by id;
if first.id then cbsum=0;
if cbsum>50 then cb2=0;
else cb2=min(50-cbsum,cb);
cbsum+cb;
run;
proc sort;
by date id;
run;
Note that CBSUM is retained across observations, due to the "summing statement" ( CBSUM+CB).
If you want to avoid sorting then you could keep a CBSUM value for each ID, in a hash object:
data want (drop=cbsum);
set have;
if _n_=1 then do;
declare hash h ();
h.definekey('id');
h.definedata('cbsum');
h.definedone();
end;
if h.find()^=0 then cbsum=0;
if cbsum>50 then cb2=0;
else cb2=min(50-cbsum,cb);
cbsum+cb;
h.replace();
run;
You mean, something like this?
data have;
input Id $ date :date9. cb;
format date date5.;
datalines;
X 1jan2019 27
Y 1jan2019 47
X 2jan2019 10
Y 2jan2019 13
X 3jan2019 37
;
proc sort data=have; by id date; run;
%let limit=50;
data want;
s = 0;
do until(last.id);
set have; by id;
cb2 = max(0, min(cb, &limit. - s));
s = s + cb;
output;
end;
drop s;
run;
proc sort data=want; by date id; run;
proc print data=want noobs; run;
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!
Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.