DATA Step, Macro, Functions and more

Selecting distinct Combinations

Accepted Solution Solved
Reply
Frequent Contributor
Posts: 103
Accepted Solution

Selecting distinct Combinations

Hi there:

 

i have this 5 names:

 

data have;

input names$;

cards;

aaaa

bbbb

cccc

dddd

eeee;

 

now need to obtain the combination NOT ALEATORY, by steps like this,

i) the firt table i need to obtain is simple: is the raw data;

ii)the second table is where my problems begin because i need to combinate the names in couples and it can not be repeated like this:

 

want:

 

aaaa bbbb

aaaa cccc

aaaa dddd

aaaa eeee

bbbb cccc

bbbb dddd

bbbb eeee

cccc dddd

cccc eeee

dddd eeee

 

and the third table comes in triplets and like this untill get the final combination where all five names are

 

aaaa bbbb cccc dddd eeee

 

Thanks a lot


Accepted Solutions
Solution
‎12-10-2016 07:19 PM
Super User
Posts: 19,770

Re: Selecting distinct Combinations

Posted in reply to jonatan_velarde

Use CALL LEXCOMB or CALL ALLCOMB 

http://support.sas.com/documentation/cdl/en/lefunctionsref/69762/HTML/default/viewer.htm#p0yvzzxdzou...

 

The CALL LEXCOMB routine generates all distinct combinations of the nonmissing values of n variables taken k at a time in lexicographic order. The CALL ALLCOMB routine generates all combinations of the values of n variables taken k at a time in a minimal change order.

 

The documentation has an example and here's a specific solution to your question. 

 

data want;
*can load temporary array from dataset if required;
array x[5] $4 _temporary_ ('aaaa' 'bbbb' 'cccc' 'dddd' 'eeee');
*array for output;
array y(5) $4;

n=dim(x);

*loop overall all possible output ranges;
do k=1 to n;

*Determine number of combinations required;
ncomb=comb(n, k);

*Create all combinations;
do j=1 to ncomb;

*create the combination;
call lexcomb(j, k, of x[*]);

*Set all values to missing;
call missing(of y(*));

*Copy over the values to the array for output;
do i=1 to k;
y(i)=x(i);
end;

*output record;
output;

end;
end;

run;

proc print data=want;
run;

 

View solution in original post


All Replies
Trusted Advisor
Posts: 1,018

Re: Selecting distinct Combinations

Posted in reply to jonatan_velarde

I looked up "aleatory", and I'm not sure what you really mean.  My wikipedia look up defines aleatory (in music) as  "determined in general but depends on chance in detail."  But you say you want it "NOT ALEATORY".   So you DON'T want "determined in general but depends on chance in detail".  Sounds like you want a regular ordered list, with no randomization.

 

And that would be support by your sample list, under the title "want".  But then, just before that list why do you say "and it can not be repeated like this:". 

 

Please clarify.

 

 

Frequent Contributor
Posts: 103

Re: Selecting distinct Combinations

Thanks in advance for your point .

Yes, i need a regular ordered list in duplet, triples and quadruplets as was shown in the want example.

IF you can help me i would really apreciate

Regards
Solution
‎12-10-2016 07:19 PM
Super User
Posts: 19,770

Re: Selecting distinct Combinations

Posted in reply to jonatan_velarde

Use CALL LEXCOMB or CALL ALLCOMB 

http://support.sas.com/documentation/cdl/en/lefunctionsref/69762/HTML/default/viewer.htm#p0yvzzxdzou...

 

The CALL LEXCOMB routine generates all distinct combinations of the nonmissing values of n variables taken k at a time in lexicographic order. The CALL ALLCOMB routine generates all combinations of the values of n variables taken k at a time in a minimal change order.

 

The documentation has an example and here's a specific solution to your question. 

 

data want;
*can load temporary array from dataset if required;
array x[5] $4 _temporary_ ('aaaa' 'bbbb' 'cccc' 'dddd' 'eeee');
*array for output;
array y(5) $4;

n=dim(x);

*loop overall all possible output ranges;
do k=1 to n;

*Determine number of combinations required;
ncomb=comb(n, k);

*Create all combinations;
do j=1 to ncomb;

*create the combination;
call lexcomb(j, k, of x[*]);

*Set all values to missing;
call missing(of y(*));

*Copy over the values to the array for output;
do i=1 to k;
y(i)=x(i);
end;

*output record;
output;

end;
end;

run;

proc print data=want;
run;

 

Frequent Contributor
Posts: 103

Re: Selecting distinct Combinations

This is awesome.

 

bs y1 y2 y3 y4 y5 n k ncomb j i
1 aaaa         5 1 5 1 2
2 bbbb         5 1 5 2 2
3 cccc         5 1 5 3 2
4 dddd         5 1 5 4 2
5 eeee         5 1 5 5 2
6 aaaa bbbb       5 2 10 1 3
7 aaaa cccc       5 2 10 2 3
8 aaaa dddd       5 2 10 3 3
9 aaaa eeee       5 2 10 4 3
10 bbbb cccc       5 2 10 5 3
11 bbbb dddd       5 2 10 6 3
12 bbbb eeee       5 2 10 7 3
13 cccc dddd       5 2 10 8 3
14 cccc eeee       5 2 10 9 3
15 dddd eeee       5 2 10 10 3
16 aaaa bbbb cccc     5 3 10 1 4
17 aaaa bbbb dddd     5 3 10 2 4
18 aaaa bbbb eeee     5 3 10 3 4
19 aaaa cccc dddd     5 3 10 4 4
20 aaaa cccc eeee     5 3 10 5 4
21 aaaa dddd eeee     5 3 10 6 4
22 bbbb cccc dddd     5 3 10 7 4
23 bbbb cccc eeee     5 3 10 8 4
24 bbbb dddd eeee     5 3 10 9 4
25 cccc dddd eeee     5 3 10 10 4
26 aaaa bbbb cccc dddd   5 4 5 1 5
27 aaaa bbbb cccc eeee   5 4 5 2 5
28 aaaa bbbb dddd eeee   5 4 5 3 5
29 aaaa cccc dddd eeee   5 4 5 4 5
30 bbbb cccc dddd eeee   5 4 5 5 5
31 aaaa bbbb cccc dddd eeee 5 5 1 1  
Super User
Posts: 5,497

Re: Selecting distinct Combinations

Reeza's approach has all the bells and whistles, and is better than what I have below.  Still, it's worth noting that you can get almost the same result with a simple program:

 

data want;

do name1='aaaa', ' ';

do name2='bbbb', ' ';

do name3='cccc', ' ';

do name4='dddd', ' ';

do name5='eeee', ' ';

   output;

end; end; end; end; end;

run;

 

The name values don't always begin with NAME1, and you also get the empty set as a combination.  But the programming is pretty easy.

Super User
Posts: 10,018

Re: Selecting distinct Combinations

Posted in reply to Astounding
Astounding,
There are two simple way

1)
data have;
input x $;
cards;
aaaa
bbbb
cccc
dddd
eeee
;
run;
proc transpose data=have out=temp;
 var x;
run;

proc summary data=temp;
 class col:;
 output out=x;
run;

data want;
 set x;
 length want $ 200;
 want=catx('|',of col:);
 keep want;
run;



2)
data want;
array z{5} $ ('aaaa' 'bbbb' 'cccc' 'dddd' 'eeee');
array x{5} ;

length want $ 200;
n=dim(x);
k=-1;
nsubs=2**n;
do i=1 to nsubs;
 rc=graycode(k, of x{*});
 call missing(want);
 do j=1 to n;
  if x{j}=1 then want=catx('|',want,z{j});
 end;
 output;
end;
keep want ;
run;




Super User
Posts: 19,770

Re: Selecting distinct Combinations

@Ksharp Graycode?

Super User
Posts: 10,018

Re: Selecting distinct Combinations

@Reeza ,

Yes. graycode() would give you all the combinations from 1 to n.

☑ This topic is solved.

Need further help from the community? Please ask a new question.

Discussion stats
  • 8 replies
  • 481 views
  • 10 likes
  • 5 in conversation