Hi,
Here is yet another solution, While I have used some code from previous contributors, I've used Custom written function via Proc FCMP to produce and return all possible course combinations.
The getCombos(values [*] $, sep $) $; user function, accepts an array and a separator character, and returns a separated String of course combinations. The logic implemented inside that function was inspired from an old SUGI 29 paper .
proc fcmp
outlib=sasuser.functions.customFunctions;
function getCombos(values [*] $, sep $) $;
length combos $100 l_sep $1;
length i vCount binaryDigit 4;
length max_Type_ start i_tmp 8;
length final_combo $1000;
l_sep=ifc (sep='','I',sep) ;
*put values[*];
vCount=0;
do i=1 to dim(values);
vCount+ifc(values[i]='',0,1);
end;
max_Type_ = 2**vCount - 1;
*put max_Type_;
/* Loop through till max_Type_ is reached*/
do start=0 to max_Type_;
i_tmp = start;
/* Loop through all passed-in values */
do j=vCount to 1 by -1;
binaryDigit= int(i_tmp/(2**(j-1)) );
if (binaryDigit = 1) then
do;
combos = catx(',',combos,values[(vCount-j+1)]);
* Decrement i_tmp if binaryDigit is in types binary representation;
i_tmp = i_tmp - 2**(j-1);
end;
end; /*End of j=vCount to 1 by -1*/
/* Only maintain combinations of more than 1 value */
if (index(combos,',') GT 0) then
do;
*put combos;
final_combo = catx(l_sep,final_combo,combos);
*put final_combo;
end;
combos='';
end; /* End of start=0 to max_Type_*/
return (final_combo);
endsub;
run;
options cmplib=(sasuser.functions);
data student;
input Student_ID$ Course$ Gender$;
datalines;
1001 Math F
1001 Computer F
1001 Physics F
1002 Math M
1002 Physics M
1003 Math M
1003 Chemstry M
1003 Computer M
1003 Physics M
1004 Chemstry M
1004 Computer M
1004 Physics M
;
run;
proc sort data=student;
by student_id course;
run;
data want(keep=student_id gender crse_combo);
array _crse{10} $9 _temporary_;
retain nc 0;
set student;
by student_id;
length courses $1000;
if first.student_id then
do;
call missing(of _crse{*});
nc=0;
end;
nc+1;
_crse{nc}=course;
if ((last.student_id) and (nc > 1));
courses = getCombos(_crse, "~");
*put courses=;
comboCount=countc(courses,'~')+1;
do c=1 to comboCount;
crse_combo=scan(courses,c,'~');
combo_size=countc(crse_combo,',')+1;
crse_combo= put(combo_size,2.) || ': ' || crse_combo;
output;
end;
run;
proc tabulate data=want noseps;
class gender crse_combo;
tables crse_combo=' ',gender=' '*N=' '*f=4.
/ rts=100 box='Size / Course List' misstext='0';
run;
Hope this helps,
Ahmed
... View more