<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: How to create new rows of all possible combinations (without using Cartesian merging) in SAS Programming</title>
    <link>https://communities.sas.com/t5/SAS-Programming/How-to-create-new-rows-of-all-possible-combinations-without/m-p/719246#M222682</link>
    <description>&lt;BLOCKQUOTE&gt;&lt;HR /&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/365070"&gt;@KS99&lt;/a&gt;&amp;nbsp;wrote:&lt;BR /&gt;
&lt;P&gt;Dear mkeintz,&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Thank you for helping me a second time!&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Your codes work perfectly.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The codes you wrote are very short and exquisite.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Do you mind if I ask you a further question?&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Today I studied hash object for the first time, and looked at your codes and comments again.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;But what I don't understand from your comments are:&amp;nbsp;&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;&lt;STRONG&gt;The h.find() method returns a zero for success and a non-zero for failures.&amp;nbsp; This will retrieve the first instance of each CUSIP.&lt;/STRONG&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;The "until (h.find.next)^=0" performs a h.find_next() method at the bottom of each loop iteration, and returns a zero for successful retrieved of the next item of the same cusip.&amp;nbsp;&lt;/STRONG&gt;&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;How does h.find() function work exactly?&amp;nbsp;&lt;/P&gt;
&lt;P&gt;It seems to be used in a variety of merging, left full join, etc.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;You can give me a quick answer, cos I am ashamed to take your precious time;)&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Many thanks!&amp;nbsp;&lt;/P&gt;
&lt;P&gt;KS -&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;HR /&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;I don't know much about hash functionns - I only know how to use hash objects in SAS.&amp;nbsp; &amp;nbsp;But, according to the wikipedia entry for Hash Function,&amp;nbsp;&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;SPAN&gt;Hash functions and their &lt;EM&gt;&lt;STRONG&gt;associated hash tables&lt;/STRONG&gt;&lt;/EM&gt; are used in data storage and retrieval applications to access data in a small and nearly constant time per retrieval, and require an amount of storage space only fractionally greater than the total space required for the data or records themselves. Hashing is a computationally and storage space efficient form of data access which avoids the non-linear access time of ordered and unordered lists and structured trees, and the often exponential storage requirements of direct access of state spaces of large or variable-length keys.&lt;/SPAN&gt;&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;OL&gt;
&lt;LI&gt;&lt;SPAN&gt;This is my crude understanding:&amp;nbsp; A hash transformation is applied to the key variable(s)&amp;nbsp; - CUSIP in this case - to assign it a place in the hash table.&amp;nbsp; This is used when adding data to the hash object, and when retrieving, or even just checking whether data for the specified CUSIP is in the object&amp;nbsp; The advantage is that as your data collection grows, most other retrieval methods (like binary search) will take increasing amounts of time, whereas hash-based methods take almost no more time - even when the data is larger by an order of magnitude.&amp;nbsp; The FIND method takes the CUSIP value, applies a hash function to it, and uses the result to effectively directly address the corresponding data item in the hash - i.e. it does not "search" for the item.&lt;BR /&gt;&lt;BR /&gt;The find method is like a function in that it generates a return code, zero for success, non-zeroes for various types of failure.&amp;nbsp; As far as I can tell "failure" means only one thing - the particular key value (the hash-transformed value of your CUSIP) is not (yet) in the hash object.&amp;nbsp; The other thing that a successful find does is to retrieve the all the variables listed in the ".definedata" method from the hash object into those variables in your program.&lt;BR /&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;SPAN&gt;The default condition for SAS hash objects is one dataitem per key value.&amp;nbsp; That is, it would hold only one analyst for each cusip.&amp;nbsp; So the "multidata:'y'" parameter tells SAS to make the hash object provide for multiple analysts per cusip.&amp;nbsp; But then the problem is that FIND will only ever retrieve whichever analyst is the first in that series of analysts - all the others are unavailable via FIND.&amp;nbsp; So another method is needed to traverse all the dataitems for a given cusip value - that's &lt;EM&gt;&lt;STRONG&gt;find_next&lt;/STRONG&gt;&lt;/EM&gt;.&amp;nbsp; Like all other hash methods it returns a zero when successful, non-zero otherwise.&amp;nbsp; &amp;nbsp;That means, when it's not a zero, there are no further analysts for that given cusip in the hash object.&amp;nbsp; BTW, you can go forward via find_next,&amp;nbsp; and backwards via find_prev.&lt;BR /&gt;&lt;BR /&gt;The "do until" is just a way to tell sas to evaluate the "until" expression at the bottom of each loop iteration.&amp;nbsp; But the nice thing about the find_next method is that not only does it return a zero or non-zero for evaluation by until, it also transcribes data from the object to the corresponding sas variables (the "program data vector").&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;Another thing that might be a bit surprising: the "by 0" in "do rc=h.find by 0 until (h.find_next()^=0".&amp;nbsp; This is just shorthand for&lt;/SPAN&gt;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;rc=h.find();
do until (rc^=0);
   if ... then output;
   rc=h.find_next();
end;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
    <pubDate>Sun, 14 Feb 2021 23:32:35 GMT</pubDate>
    <dc:creator>mkeintz</dc:creator>
    <dc:date>2021-02-14T23:32:35Z</dc:date>
    <item>
      <title>How to create new rows of all possible combinations (without using Cartesian merging)</title>
      <link>https://communities.sas.com/t5/SAS-Programming/How-to-create-new-rows-of-all-possible-combinations-without/m-p/719187#M222657</link>
      <description>&lt;P&gt;Hi, I need your help!&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Suppose I have the following dataset,&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;data Network;&lt;BR /&gt;input&amp;nbsp; Cusip&amp;nbsp; Analyst;&lt;BR /&gt;cards;&lt;BR /&gt;1&amp;nbsp; 1&lt;BR /&gt;1&amp;nbsp; 2&amp;nbsp;&amp;nbsp;&lt;BR /&gt;1&amp;nbsp; 3&amp;nbsp;&lt;BR /&gt;2&amp;nbsp; 8&lt;BR /&gt;2&amp;nbsp; 9&lt;BR /&gt;2&amp;nbsp; 10&lt;BR /&gt;2&amp;nbsp; 11&lt;BR /&gt;2&amp;nbsp; 12&lt;BR /&gt;3&amp;nbsp; 45&lt;BR /&gt;3&amp;nbsp; 46&lt;BR /&gt;;&lt;BR /&gt;run;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I want to create a new dataset that looks like below,&amp;nbsp;&lt;/P&gt;&lt;P&gt;__________________________&lt;/P&gt;&lt;P&gt;Cusip Var1 Var2&amp;nbsp;&lt;/P&gt;&lt;P&gt;1&amp;nbsp; &amp;nbsp;1&amp;nbsp; &amp;nbsp; 2&lt;BR /&gt;1&amp;nbsp; &amp;nbsp;2&amp;nbsp; &amp;nbsp; 3&amp;nbsp;&amp;nbsp;&lt;BR /&gt;1&amp;nbsp; &amp;nbsp;3&amp;nbsp; &amp;nbsp; 1&lt;BR /&gt;2&amp;nbsp; &amp;nbsp;8&amp;nbsp; &amp;nbsp; 9&lt;BR /&gt;2&amp;nbsp; &amp;nbsp;9&amp;nbsp; 10&lt;BR /&gt;2 10&amp;nbsp; 11&lt;BR /&gt;2 11&amp;nbsp; 12&amp;nbsp;&lt;BR /&gt;2 12&amp;nbsp; &amp;nbsp; 8&lt;/P&gt;&lt;P&gt;2&amp;nbsp; &amp;nbsp;8&amp;nbsp; &amp;nbsp;11&lt;BR /&gt;2&amp;nbsp; &amp;nbsp;8&amp;nbsp; &amp;nbsp;10&lt;BR /&gt;2&amp;nbsp; &amp;nbsp;9&amp;nbsp; &amp;nbsp;12&lt;/P&gt;&lt;P&gt;2&amp;nbsp; &amp;nbsp;9&amp;nbsp; &amp;nbsp;11&lt;BR /&gt;2&amp;nbsp; 10&amp;nbsp; 12&amp;nbsp;&lt;BR /&gt;3&amp;nbsp; 45&amp;nbsp; 46&lt;BR /&gt;________________________&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;In other words, I want to create nC2 for each Cusip.&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I tried using Cartesian production (full merging), but cleaning the duplicates again throws me into the mire.&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Many thanks, in advance!&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Sincerely,&amp;nbsp;&lt;/P&gt;&lt;P&gt;KS -,&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sun, 14 Feb 2021 09:05:41 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/How-to-create-new-rows-of-all-possible-combinations-without/m-p/719187#M222657</guid>
      <dc:creator>KS99</dc:creator>
      <dc:date>2021-02-14T09:05:41Z</dc:date>
    </item>
    <item>
      <title>Re: How to create new rows of all possible combinations (without using Cartesian merging)</title>
      <link>https://communities.sas.com/t5/SAS-Programming/How-to-create-new-rows-of-all-possible-combinations-without/m-p/719188#M222658</link>
      <description>&lt;P&gt;Based on the solution given in next link:&lt;/P&gt;
&lt;P&gt;&lt;A href="https://communities.sas.com/t5/SAS-Programming/Permutations/m-p/325680" target="_self"&gt;https://communities.sas.com/t5/SAS-Programming/Permutations/m-p/325680&lt;/A&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I suggest to solve your issue with next steps:&lt;/P&gt;
&lt;P&gt;1) Transpose your data to have one observation per CUSIP with all ANALYST values. Of course, some of them may become missing value.&lt;/P&gt;
&lt;P&gt;2) Adapt the proposed code in the link, by defining array of all values.&lt;/P&gt;
&lt;P&gt;Make sure all values are at the beginning and missing values at the end of the array. Adapt the DO loop to end at the last non missing value.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sun, 14 Feb 2021 09:54:29 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/How-to-create-new-rows-of-all-possible-combinations-without/m-p/719188#M222658</guid>
      <dc:creator>Shmuel</dc:creator>
      <dc:date>2021-02-14T09:54:29Z</dc:date>
    </item>
    <item>
      <title>Re: How to create new rows of all possible combinations (without using Cartesian merging)</title>
      <link>https://communities.sas.com/t5/SAS-Programming/How-to-create-new-rows-of-all-possible-combinations-without/m-p/719190#M222660</link>
      <description>&lt;P&gt;Hi&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/365070"&gt;@KS99&lt;/a&gt;&amp;nbsp;,&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Just to clarify, you are looking for all 2 element combinations for each group? If yes, then the DFA(Dynamic Function Array) package may be help here. If you have any questions - ask.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;All the best&lt;/P&gt;
&lt;P&gt;Bart&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;/* data */
data Network;
input  Cusip  Analyst;
cards;
1  1
1  2  
1  3 
2  8
2  9
2  10
2  11
2  12
3  45
3  46
;
run; 


/* use the DFA package */
filename packages "%sysfunc(pathname(work))"; /* setup directory for packages */
filename SPFinit url "https://raw.githubusercontent.com/yabwon/SAS_PACKAGES/main/SPF/SPFinit.sas";
%include SPFinit; /* enable the framework */
%installPackage(DFA) /* install the package */
%loadPackage(DFA)    /* load the package content into the SAS session */

data want;
  call SmpMtbArray("Allocate", 1, 1);

  do until(last.Cusip);
    set Network;
    by Cusip;  

    i+1;
    call SmpMtbArray("Input", i, Analyst);
  end;

  call SmpMtbArray("Dim", L, H);
  put L= H=;

  do i = L to H;
    do j = i+1 to H;
      call SmpMtbArray("Output", i, Var1);
      call SmpMtbArray("Output", j, Var2);
      output;
    end;
  end;

  keep Cusip Var1 Var2;
  call missing (i, j, L, H, Var1, Var2);
run;&lt;BR /&gt;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;here is the code to compare the result and the expected data&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;proc sort data = want;
  by Cusip Var1 Var2;
run;
title "Want";
proc print data = want;
run;


/* your expected data  to compare */
data have;
input Cusip x1 x2;
  Var1 = x1 min x2;
  Var2 = x1 max x2;
keep Cusip Var1 Var2;
cards;
1   1    2
1   2    3  
1   3    1
2   8    9
2   9  10
2 10  11
2 11  12 
2 12    8
2   8   11
2   8   10
2   9   12
2   9   11
2  10  12 
3  45  46
;
run;
title "Have";
proc sort data = have;
  by Cusip Var1 Var2;
run;
proc print data = have;
run;

title "Compare";
proc compare base = have compare = want;
run;
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sun, 14 Feb 2021 10:25:53 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/How-to-create-new-rows-of-all-possible-combinations-without/m-p/719190#M222660</guid>
      <dc:creator>yabwon</dc:creator>
      <dc:date>2021-02-14T10:25:53Z</dc:date>
    </item>
    <item>
      <title>Re: How to create new rows of all possible combinations (without using Cartesian merging)</title>
      <link>https://communities.sas.com/t5/SAS-Programming/How-to-create-new-rows-of-all-possible-combinations-without/m-p/719192#M222662</link>
      <description>&lt;P&gt;Hi&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/365070"&gt;@KS99&lt;/a&gt;,&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Here's a similar array-based solution:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data want(drop=_: analyst);
array _a[100] _temporary_; /* choose dimension&amp;gt;=max(#analysts for a cusip) */
do _k=1 by 1 until(last.cusip);
  set network;
  by cusip;
  _a[_k]=analyst;
end;
do _i=1 to _k-1;
  do _j=_i+1 to _k;
    var1=_a[_i];
    var2=_a[_j];
    output;
  end;
end;
run;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Note that the above code consistently creates (var1, var2) pairs with var1&amp;lt;var2.&lt;/P&gt;</description>
      <pubDate>Sun, 14 Feb 2021 10:46:49 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/How-to-create-new-rows-of-all-possible-combinations-without/m-p/719192#M222662</guid>
      <dc:creator>FreelanceReinh</dc:creator>
      <dc:date>2021-02-14T10:46:49Z</dc:date>
    </item>
    <item>
      <title>Re: How to create new rows of all possible combinations (without using Cartesian merging)</title>
      <link>https://communities.sas.com/t5/SAS-Programming/How-to-create-new-rows-of-all-possible-combinations-without/m-p/719194#M222664</link>
      <description>&lt;P&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/32733"&gt;@FreelanceReinh&lt;/a&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Counterexample to both your: "&lt;EM&gt;Note that the above code consistently creates (var1, var2) pairs with var1&amp;lt;var2.&lt;/EM&gt;"&amp;nbsp;&lt;/P&gt;
&lt;P&gt;and the "comparing" part of my code:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data Network;
input  Cusip  Analyst;
cards;
1  3
1  2  
1  1 
;
run; &lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&lt;span class="lia-unicode-emoji" title=":slightly_smiling_face:"&gt;🙂&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;But still both codes provides correct results.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;All the best&lt;/P&gt;
&lt;P&gt;Bart&lt;/P&gt;</description>
      <pubDate>Sun, 14 Feb 2021 11:04:51 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/How-to-create-new-rows-of-all-possible-combinations-without/m-p/719194#M222664</guid>
      <dc:creator>yabwon</dc:creator>
      <dc:date>2021-02-14T11:04:51Z</dc:date>
    </item>
    <item>
      <title>Re: How to create new rows of all possible combinations (without using Cartesian merging)</title>
      <link>https://communities.sas.com/t5/SAS-Programming/How-to-create-new-rows-of-all-possible-combinations-without/m-p/719195#M222665</link>
      <description>&lt;P&gt;Oh yes. I made some tacit assumptions regarding sort order, no duplicates, ...&lt;/P&gt;</description>
      <pubDate>Sun, 14 Feb 2021 11:12:47 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/How-to-create-new-rows-of-all-possible-combinations-without/m-p/719195#M222665</guid>
      <dc:creator>FreelanceReinh</dc:creator>
      <dc:date>2021-02-14T11:12:47Z</dc:date>
    </item>
    <item>
      <title>Re: How to create new rows of all possible combinations (without using Cartesian merging)</title>
      <link>https://communities.sas.com/t5/SAS-Programming/How-to-create-new-rows-of-all-possible-combinations-without/m-p/719196#M222666</link>
      <description>&lt;P&gt;I think both your code and mine assumes only no duplicates. Order of values is irrelevant since both 1,2,3 and 3,2,1 will generate the same number of pairs.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Bart&lt;/P&gt;</description>
      <pubDate>Sun, 14 Feb 2021 11:19:39 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/How-to-create-new-rows-of-all-possible-combinations-without/m-p/719196#M222666</guid>
      <dc:creator>yabwon</dc:creator>
      <dc:date>2021-02-14T11:19:39Z</dc:date>
    </item>
    <item>
      <title>Re: How to create new rows of all possible combinations (without using Cartesian merging)</title>
      <link>https://communities.sas.com/t5/SAS-Programming/How-to-create-new-rows-of-all-possible-combinations-without/m-p/719198#M222667</link>
      <description>&lt;P&gt;An alternative (but slower) solution using PROC SQL:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;proc sql;
create table want as
select a.cusip, a.analyst as var1, b.analyst as var2
from network a, network b
where a.cusip=b.cusip &amp;amp; a.analyst&amp;lt;b.analyst
order by 1,2,3;
quit;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;BLOCKQUOTE&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/35763"&gt;@yabwon&lt;/a&gt;&amp;nbsp;wrote:&lt;BR /&gt;
&lt;P&gt;I think both your code and mine assumes only no duplicates. Order of values is irrelevant since both 1,2,3 and 3,2,1 will generate the same number of pairs.&lt;/P&gt;
&lt;HR /&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/35763"&gt;@yabwon&lt;/a&gt;: Sure. The "assumptions" referred to my "var1&amp;lt;var2" statement.&lt;/P&gt;</description>
      <pubDate>Sun, 14 Feb 2021 11:36:24 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/How-to-create-new-rows-of-all-possible-combinations-without/m-p/719198#M222667</guid>
      <dc:creator>FreelanceReinh</dc:creator>
      <dc:date>2021-02-14T11:36:24Z</dc:date>
    </item>
    <item>
      <title>Re: How to create new rows of all possible combinations (without using Cartesian merging)</title>
      <link>https://communities.sas.com/t5/SAS-Programming/How-to-create-new-rows-of-all-possible-combinations-without/m-p/719204#M222670</link>
      <description>&lt;P&gt;Next code is tested. I need replace the ALLPERM() function into LEXPERM() function in order to omit missing values created by PROC TRANSPOSE.&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data Network;
input  Cusip  Analyst;
cards;
1  1
1  2  
1  3 
2  8
2  9
2  10
2  11
2  12
3  45
3  46
;
run; 

proc transpose data=Network out=data1;
by cusip;
var Analyst;
run;

data want;
 set data1;
     array colx {*} col:;
     lasti = dim(colx);
     do i=1 to dim(colx);
        if missing(colx(i)) then do;
           lasti = i-1; leave;
        end;
     end;
     
     nfact = fact(lasti); put _N_= lasti= nfact=;
     do i=1 to nfact;
        call LEXPERM (i, of colx[*]);
        output;
     end;
     drop lasti i nfact;
run;
     
     
     
&lt;/CODE&gt;&lt;/PRE&gt;</description>
      <pubDate>Sun, 14 Feb 2021 12:59:23 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/How-to-create-new-rows-of-all-possible-combinations-without/m-p/719204#M222670</guid>
      <dc:creator>Shmuel</dc:creator>
      <dc:date>2021-02-14T12:59:23Z</dc:date>
    </item>
    <item>
      <title>Re: How to create new rows of all possible combinations (without using Cartesian merging)</title>
      <link>https://communities.sas.com/t5/SAS-Programming/How-to-create-new-rows-of-all-possible-combinations-without/m-p/719218#M222671</link>
      <description>&lt;P&gt;If you only care about combinations, and don't care about permutations (ie.&amp;nbsp; &amp;nbsp; (var1,var2) can be either (8,9) or (9,8), then this can be straightforward in a single data step, using hash objects that allow duplicates for each key value:&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data Network;
input  Cusip  Analyst;
cards;
1  1
1  2  
1  3 
2  8
2  9
2  10
2  11
2  12
3  45
3  46
run; 

data want (drop=rc);
  set network (rename=(analyst=var1)) network (obs=0 rename=(analyst=var2));

  if _n_=1 then do;
    declare hash h (dataset:'network (rename=(analyst=var2))',multidata:'y');
      h.definekey('cusip');
      h.definedata('var2');
      h.definedone();
  end;
  do rc=h.find() by 0 until (h.find_next()^=0);
    if var1&amp;lt;var2 then output;
  end;
run;
    
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Note that it doesn't matter what order your original data has.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;&amp;nbsp; The SET statement has data set network specified a second time, but with OBS=0.&amp;nbsp; That's just to provide the rename of analyst to var2, thereby insuring that var2 has all the attributes of the original variable.&lt;/LI&gt;
&lt;LI&gt;The hash object gets declared once, during the first iteration of the data step.&amp;nbsp; Think of it as a lookup table, keyed on the CUSIP variable.&amp;nbsp; But since CUSIP:ANALYST is not 1 to 1, but 1 to many, you have to tell the sas that each CUSIP key can have multiple data items (multiple ANALYST values).&lt;/LI&gt;
&lt;LI&gt;The hash object in this case causes a complete pass through the NETWORK dataset to pre-populate the object.&lt;/LI&gt;
&lt;LI&gt;The definedata method tell sas what vars shold be retrieved (and stored in) the hash object.&lt;BR /&gt;&lt;BR /&gt;&lt;/LI&gt;
&lt;LI&gt;The h.find() method returns a zero for success and a non-zero for failures.&amp;nbsp; This will retrieve the first instance of each CUSIP.&lt;/LI&gt;
&lt;LI&gt;Inside the loop&amp;nbsp; &amp;nbsp;"if var1&amp;lt;var2" prevent duplicates, regardless of var1,var2 permutation.&lt;/LI&gt;
&lt;LI&gt;The "until (h.find.next)^=0" performs a h.find_next() method at the bottom of each loop iteration, and returns a zero for successful retrieved of the next item of the same cusip.&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sun, 14 Feb 2021 15:44:29 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/How-to-create-new-rows-of-all-possible-combinations-without/m-p/719218#M222671</guid>
      <dc:creator>mkeintz</dc:creator>
      <dc:date>2021-02-14T15:44:29Z</dc:date>
    </item>
    <item>
      <title>Re: How to create new rows of all possible combinations (without using Cartesian merging)</title>
      <link>https://communities.sas.com/t5/SAS-Programming/How-to-create-new-rows-of-all-possible-combinations-without/m-p/719223#M222672</link>
      <description>&lt;P&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/31461"&gt;@mkeintz&lt;/a&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Mark, great solution!&lt;/P&gt;
&lt;P&gt;If I may, with small extension, it is also "doubled-data-proof"&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data Network;
input  Cusip  Analyst;
cards;
1  3
1  3
1  2
1  1
1  3
run; 

data _null_;
  set network (rename=(analyst=var1)) network (obs=0 rename=(analyst=var2)) end=eof;

  if _n_=1 then do;
    declare hash h (dataset:'network (rename=(analyst=var2))',multidata:'y');
      h.definekey('cusip');
      h.definedata('var2');
      h.definedone();

      declare hash W(ordered:"A");
      W.definekey('cusip', 'var1', 'var2');
      W.definedone();
  end;
  do rc=h.find() by 0 until (h.find_next()^=0);
    if var1&amp;lt;var2 then W.replace();
  end;

  if EOF then W.output(dataset:"want");
run;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;All the best&lt;/P&gt;
&lt;P&gt;Bart&lt;/P&gt;</description>
      <pubDate>Sun, 14 Feb 2021 15:23:54 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/How-to-create-new-rows-of-all-possible-combinations-without/m-p/719223#M222672</guid>
      <dc:creator>yabwon</dc:creator>
      <dc:date>2021-02-14T15:23:54Z</dc:date>
    </item>
    <item>
      <title>Re: How to create new rows of all possible combinations (without using Cartesian merging)</title>
      <link>https://communities.sas.com/t5/SAS-Programming/How-to-create-new-rows-of-all-possible-combinations-without/m-p/719228#M222674</link>
      <description>&lt;P&gt;Just as an alternative&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data Network;
input  Cusip Analyst;
cards;
1  1  
1  2  
1  3  
2  8  
2  9  
2  11 
2  10 
2  12 
3  45 
3  46 
;

proc transpose data=Network out=wide prefix = a;
    by Cusip;
    id Analyst;
    var Analyst;
run;

proc summary data = wide missing;
   by Cusip;
   class a:;
   ways 2;
   output out = temp / ways;
run;

data want(keep = Cusip var1 var2);
   set temp;
   if n(of a:) = 2;
   var1 = largest(2, of a:);
   var2 = largest(1, of a:);
run;&lt;/CODE&gt;&lt;/PRE&gt;</description>
      <pubDate>Sun, 14 Feb 2021 19:09:11 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/How-to-create-new-rows-of-all-possible-combinations-without/m-p/719228#M222674</guid>
      <dc:creator>PeterClemmensen</dc:creator>
      <dc:date>2021-02-14T19:09:11Z</dc:date>
    </item>
    <item>
      <title>Re: How to create new rows of all possible combinations (without using Cartesian merging)</title>
      <link>https://communities.sas.com/t5/SAS-Programming/How-to-create-new-rows-of-all-possible-combinations-without/m-p/719239#M222676</link>
      <description>Hi, yabwon!&lt;BR /&gt;&lt;BR /&gt;Thank you very much, yabwon!&lt;BR /&gt;I will download the package and carefully study them.&lt;BR /&gt;I really appreciate your help and discussions!&lt;BR /&gt;&lt;BR /&gt;Sincerely,&lt;BR /&gt;KS -,&lt;BR /&gt;</description>
      <pubDate>Sun, 14 Feb 2021 22:48:19 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/How-to-create-new-rows-of-all-possible-combinations-without/m-p/719239#M222676</guid>
      <dc:creator>KS99</dc:creator>
      <dc:date>2021-02-14T22:48:19Z</dc:date>
    </item>
    <item>
      <title>Re: How to create new rows of all possible combinations (without using Cartesian merging)</title>
      <link>https://communities.sas.com/t5/SAS-Programming/How-to-create-new-rows-of-all-possible-combinations-without/m-p/719241#M222678</link>
      <description>Thank you Reinhard!&lt;BR /&gt;I will apply them for my future analysis!&lt;BR /&gt;&lt;BR /&gt;Sincerely,&lt;BR /&gt;KS -,&lt;BR /&gt;</description>
      <pubDate>Sun, 14 Feb 2021 22:49:26 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/How-to-create-new-rows-of-all-possible-combinations-without/m-p/719241#M222678</guid>
      <dc:creator>KS99</dc:creator>
      <dc:date>2021-02-14T22:49:26Z</dc:date>
    </item>
    <item>
      <title>Re: How to create new rows of all possible combinations (without using Cartesian merging)</title>
      <link>https://communities.sas.com/t5/SAS-Programming/How-to-create-new-rows-of-all-possible-combinations-without/m-p/719244#M222680</link>
      <description>&lt;P&gt;Dear mkeintz,&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Thank you for helping me a second time!&amp;nbsp;&lt;/P&gt;&lt;P&gt;Your codes work perfectly.&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;The codes you wrote are very short and exquisite.&amp;nbsp;&lt;/P&gt;&lt;P&gt;Do you mind if I ask you a further question?&amp;nbsp;&lt;/P&gt;&lt;P&gt;Today I studied hash object for the first time, and looked at your codes and comments again.&amp;nbsp;&lt;/P&gt;&lt;P&gt;But what I don't understand from your comments are:&amp;nbsp;&lt;/P&gt;&lt;OL&gt;&lt;LI&gt;&lt;STRONG&gt;The h.find() method returns a zero for success and a non-zero for failures.&amp;nbsp; This will retrieve the first instance of each CUSIP.&lt;/STRONG&gt;&lt;/LI&gt;&lt;LI&gt;&lt;STRONG&gt;The "until (h.find.next)^=0" performs a h.find_next() method at the bottom of each loop iteration, and returns a zero for successful retrieved of the next item of the same cusip.&amp;nbsp;&lt;/STRONG&gt;&lt;/LI&gt;&lt;/OL&gt;&lt;P&gt;How does h.find() function work exactly?&amp;nbsp;&lt;/P&gt;&lt;P&gt;It seems to be used in a variety of merging, left full join, etc.&amp;nbsp;&lt;/P&gt;&lt;P&gt;You can give me a quick answer, cos I am ashamed to take your precious time;)&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Many thanks!&amp;nbsp;&lt;/P&gt;&lt;P&gt;KS -&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sun, 14 Feb 2021 22:55:20 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/How-to-create-new-rows-of-all-possible-combinations-without/m-p/719244#M222680</guid>
      <dc:creator>KS99</dc:creator>
      <dc:date>2021-02-14T22:55:20Z</dc:date>
    </item>
    <item>
      <title>Re: How to create new rows of all possible combinations (without using Cartesian merging)</title>
      <link>https://communities.sas.com/t5/SAS-Programming/How-to-create-new-rows-of-all-possible-combinations-without/m-p/719246#M222682</link>
      <description>&lt;BLOCKQUOTE&gt;&lt;HR /&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/365070"&gt;@KS99&lt;/a&gt;&amp;nbsp;wrote:&lt;BR /&gt;
&lt;P&gt;Dear mkeintz,&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Thank you for helping me a second time!&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Your codes work perfectly.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The codes you wrote are very short and exquisite.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Do you mind if I ask you a further question?&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Today I studied hash object for the first time, and looked at your codes and comments again.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;But what I don't understand from your comments are:&amp;nbsp;&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;&lt;STRONG&gt;The h.find() method returns a zero for success and a non-zero for failures.&amp;nbsp; This will retrieve the first instance of each CUSIP.&lt;/STRONG&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;The "until (h.find.next)^=0" performs a h.find_next() method at the bottom of each loop iteration, and returns a zero for successful retrieved of the next item of the same cusip.&amp;nbsp;&lt;/STRONG&gt;&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;How does h.find() function work exactly?&amp;nbsp;&lt;/P&gt;
&lt;P&gt;It seems to be used in a variety of merging, left full join, etc.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;You can give me a quick answer, cos I am ashamed to take your precious time;)&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Many thanks!&amp;nbsp;&lt;/P&gt;
&lt;P&gt;KS -&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;HR /&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;I don't know much about hash functionns - I only know how to use hash objects in SAS.&amp;nbsp; &amp;nbsp;But, according to the wikipedia entry for Hash Function,&amp;nbsp;&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;SPAN&gt;Hash functions and their &lt;EM&gt;&lt;STRONG&gt;associated hash tables&lt;/STRONG&gt;&lt;/EM&gt; are used in data storage and retrieval applications to access data in a small and nearly constant time per retrieval, and require an amount of storage space only fractionally greater than the total space required for the data or records themselves. Hashing is a computationally and storage space efficient form of data access which avoids the non-linear access time of ordered and unordered lists and structured trees, and the often exponential storage requirements of direct access of state spaces of large or variable-length keys.&lt;/SPAN&gt;&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;OL&gt;
&lt;LI&gt;&lt;SPAN&gt;This is my crude understanding:&amp;nbsp; A hash transformation is applied to the key variable(s)&amp;nbsp; - CUSIP in this case - to assign it a place in the hash table.&amp;nbsp; This is used when adding data to the hash object, and when retrieving, or even just checking whether data for the specified CUSIP is in the object&amp;nbsp; The advantage is that as your data collection grows, most other retrieval methods (like binary search) will take increasing amounts of time, whereas hash-based methods take almost no more time - even when the data is larger by an order of magnitude.&amp;nbsp; The FIND method takes the CUSIP value, applies a hash function to it, and uses the result to effectively directly address the corresponding data item in the hash - i.e. it does not "search" for the item.&lt;BR /&gt;&lt;BR /&gt;The find method is like a function in that it generates a return code, zero for success, non-zeroes for various types of failure.&amp;nbsp; As far as I can tell "failure" means only one thing - the particular key value (the hash-transformed value of your CUSIP) is not (yet) in the hash object.&amp;nbsp; The other thing that a successful find does is to retrieve the all the variables listed in the ".definedata" method from the hash object into those variables in your program.&lt;BR /&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;SPAN&gt;The default condition for SAS hash objects is one dataitem per key value.&amp;nbsp; That is, it would hold only one analyst for each cusip.&amp;nbsp; So the "multidata:'y'" parameter tells SAS to make the hash object provide for multiple analysts per cusip.&amp;nbsp; But then the problem is that FIND will only ever retrieve whichever analyst is the first in that series of analysts - all the others are unavailable via FIND.&amp;nbsp; So another method is needed to traverse all the dataitems for a given cusip value - that's &lt;EM&gt;&lt;STRONG&gt;find_next&lt;/STRONG&gt;&lt;/EM&gt;.&amp;nbsp; Like all other hash methods it returns a zero when successful, non-zero otherwise.&amp;nbsp; &amp;nbsp;That means, when it's not a zero, there are no further analysts for that given cusip in the hash object.&amp;nbsp; BTW, you can go forward via find_next,&amp;nbsp; and backwards via find_prev.&lt;BR /&gt;&lt;BR /&gt;The "do until" is just a way to tell sas to evaluate the "until" expression at the bottom of each loop iteration.&amp;nbsp; But the nice thing about the find_next method is that not only does it return a zero or non-zero for evaluation by until, it also transcribes data from the object to the corresponding sas variables (the "program data vector").&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;Another thing that might be a bit surprising: the "by 0" in "do rc=h.find by 0 until (h.find_next()^=0".&amp;nbsp; This is just shorthand for&lt;/SPAN&gt;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;rc=h.find();
do until (rc^=0);
   if ... then output;
   rc=h.find_next();
end;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sun, 14 Feb 2021 23:32:35 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/How-to-create-new-rows-of-all-possible-combinations-without/m-p/719246#M222682</guid>
      <dc:creator>mkeintz</dc:creator>
      <dc:date>2021-02-14T23:32:35Z</dc:date>
    </item>
    <item>
      <title>Re: How to create new rows of all possible combinations (without using Cartesian merging)</title>
      <link>https://communities.sas.com/t5/SAS-Programming/How-to-create-new-rows-of-all-possible-combinations-without/m-p/723351#M224446</link>
      <description>Dear Mkeintz&lt;BR /&gt;&lt;BR /&gt;Thank you very much for your detailed explanations!&lt;BR /&gt;Only got back to SAS community after an extended span of research.&lt;BR /&gt;Wish you a very good rest of the day!&lt;BR /&gt;&lt;BR /&gt;KS -,&lt;BR /&gt;&lt;BR /&gt;&lt;BR /&gt;</description>
      <pubDate>Thu, 04 Mar 2021 03:30:13 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/How-to-create-new-rows-of-all-possible-combinations-without/m-p/723351#M224446</guid>
      <dc:creator>KS99</dc:creator>
      <dc:date>2021-03-04T03:30:13Z</dc:date>
    </item>
  </channel>
</rss>

