I have a list of variable names, and want to get all possible combinations of any number of variables from that list. Separately, each variable has a flag value of 0 or 1, for each combination, I also want to single out the variables with flag of 1 and put them together in a separate field. Also, I want a field with the number of variables selected, as well as a field with the number of flagged variables.
Example:
I start with this list
Name | Flag |
V1 | 1 |
V2 | 0 |
V3 | 1 |
I want to get to this list:
Combo | Flagged_Vars | Num_Var | Num_Flag_Var |
V1 | V1 | 1 | 1 |
V2 | 1 | 0 | |
V3 | V3 | 1 | 1 |
V1 V2 | V1 | 2 | 1 |
V1 V3 | V1 V3 | 2 | 2 |
V2 V3 | V3 | 2 | 1 |
V1 V2 V3 | V1 V3 | 3 | 3 |
Thank you!
data have;
input Name $ Flag;
cards;
V1 1
V2 0
V3 1
;
%let dsid=%sysfunc(open(have));
%let nobs=%sysfunc(attrn(&dsid,nlobs));
%let dsid=%sysfunc(close(&dsid));
data want;
set have end=last;
length combo Flagged_Vars $ 200;
array x{&nobs};
array n{&nobs} $ 32 _temporary_;
array f{&nobs} _temporary_;
n{_n_}=name;
f{_n_]=flag;
if last then do;
k=-1;
do i=1 to 2**&nobs;
rc=graycode(k, of x{*});
call missing(combo,Flagged_Vars);
Num_Flag_Var=0;
do j=1 to &nobs;
if x{j}=1 then do;combo=catx(' ',combo,n{j}); Num_Flag_Var+f{j}; end;
if x{j}=1 and f{j}=1 then Flagged_Vars=catx(' ',Flagged_Vars,n{j});
end;
Num_Var=countw(combo);
if Num_Var ne 0 then output;
end;
end;
keep combo Flagged_Vars Num_Var Num_Flag_Var;
run;
I wrote this myself and I think it gives what I want. Thanks all.
data varlist;
length name $32.;
input name class_flag;
cards4;
var1 0
var2 1
var3 1
var4 0
;;;;
run;
%macro exhaust();
data varlist;
set varlist;
id+1;
if class_flag=1 then class_name=name;
run;
data combo_all;set _null_;run;
proc sql;select count(*) into: varct from varlist;quit;
%put &varct.;
%do i=1 %to &varct.;
%if &i.=1 %then %do;
data combo;
set varlist (rename=(name=Var_Combo class_flag=num_flag));
num_var=1;
if num_flag=1 then Class_Var=class_name;
drop flag_name;
run;
%end;
%if &i.>1 %then %do;
proc sql;
create table combo as
select
strip(a.Var_Combo)||" "||strip(b.name) as Var_Combo,
strip(a.Class_Var)||" "||strip(b.class_name) as Class_Var,
&i. as Num_Var,
a.num_flag+b.class_flag as Num_Flag,
max(a.id,b.id) as id
from combo as a, varlist as b
where a.id < b.id
;
quit;
%end;
data combo_all;
set combo_all combo;
run;
%end;
%mend exhaust;
%exhaust();
data have;
input Name $ Flag;
cards;
V1 1
V2 0
V3 1
;
%let dsid=%sysfunc(open(have));
%let nobs=%sysfunc(attrn(&dsid,nlobs));
%let dsid=%sysfunc(close(&dsid));
data want;
set have end=last;
length combo Flagged_Vars $ 200;
array x{&nobs};
array n{&nobs} $ 32 _temporary_;
array f{&nobs} _temporary_;
n{_n_}=name;
f{_n_]=flag;
if last then do;
k=-1;
do i=1 to 2**&nobs;
rc=graycode(k, of x{*});
call missing(combo,Flagged_Vars);
Num_Flag_Var=0;
do j=1 to &nobs;
if x{j}=1 then do;combo=catx(' ',combo,n{j}); Num_Flag_Var+f{j}; end;
if x{j}=1 and f{j}=1 then Flagged_Vars=catx(' ',Flagged_Vars,n{j});
end;
Num_Var=countw(combo);
if Num_Var ne 0 then output;
end;
end;
keep combo Flagged_Vars Num_Var Num_Flag_Var;
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.