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;
Good news: We've extended SAS Hackathon registration until Sept. 12, so you still have time to be part of our biggest event yet – our five-year anniversary!
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.
Ready to level-up your skills? Choose your own adventure.