Just aggregate for each MONTH nested under each GROUPID. Tricky part is knowing when you are on the first month for a GROUPID since it could have multiple observations. So make your own month number counter.
First let's add a duplicate month so the test data is more complete:
data have;
input GroupID Month IndividualID ;
cards;
123456 202401 111
123456 202401 222
123456 202401 333
123456 202402 111
123456 202402 222
123456 202403 444
123456 202403 111
123456 202403 222
123456 202402 444
135798 202401 555
135798 202401 666
135798 202402 555
135798 202402 666
;
So generate the list for a month. lag the value. Make sure not to use the lagged value on the first month for a group. Write the observation before incrementing the month counter so the output dataset is not confusing.
proc sort data=have;
by GroupID month IndividualID ;
run;
data want;
do until(last.month);
set have;
by GroupID month IndividualID ;
if first.groupid then monthno=1;
length all_ids $200;
all_ids=catx('-',all_ids,IndividualID);
end;
lag_ids = lag(all_ids);
if monthno=1 then do;
changed=0;
lag_ids=' ';
end;
else changed= (lag_ids ne all_ids);
output;
monthno+1;
drop individualid;
run;
Results
Group
Obs ID Month monthno all_ids lag_ids changed
1 123456 202401 1 111-222-333 0
2 123456 202402 2 111-222-444 111-222-333 1
3 123456 202403 3 111-222-444 111-222-444 0
4 135798 202401 1 555-666 0
5 135798 202402 2 555-666 555-666 0
Or just remember the first month for each group.
data want;
do until(last.month);
set have;
by GroupID month IndividualID ;
if first.groupid then firstmonth=month;
retain firstmonth;
length all_ids $200;
all_ids=catx('-',all_ids,IndividualID);
end;
changed= (all_ids ne lag(all_ids));
if month=firstmonth then changed=0;
drop individualid firstmonth;
run;
... View more