<?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: Allocating numbers from &amp;quot;-n&amp;quot; to &amp;quot;+n&amp;quot; while ranking a variable by group in SAS Programming</title>
    <link>https://communities.sas.com/t5/SAS-Programming/Allocating-numbers-from-quot-n-quot-to-quot-n-quot-while-ranking/m-p/400905#M278327</link>
    <description>&lt;P&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/166516"&gt;@Saba1&lt;/a&gt;&lt;/P&gt;&lt;P&gt;As you state that your data has millions of observations, it may be more efficient if you can do the calculation without sorting (assuming that you initial data is sorted by ID and YEAR):&lt;/P&gt;&lt;PRE&gt;data want;
  array values(100) 8 _temporary_;
  npos=0;
  nneg=0;
  n0=0;
  do _N_=1 by 1 until(last.id);
    set have(keep=id ret);
    by id;
    values(_N_)=ret;
    if ret&amp;lt;0 then
      nneg+1; /* number of negative values */
    else if ret&amp;gt;0 then
      npos+1; /* number of positive values */
    else
      n0+1; /* number of zeroes */
    end;
  call sortn(of values(*));
  do until(last.id);
    set have;
    by id;
    _N_=whichn(ret,of values(*));
    if ret=0 then
      rank=0;
    else if ret&amp;lt;0 then
      rank=_N_-100+npos+n0-1;
    else
      rank=_N_-100+npos;
    values(_N_)=.; /* set missing, so that next record with same value gets next rank */
    output;
    end;
run;

&lt;/PRE&gt;&lt;P&gt;If two years have the same ID and RET value, the program assigns the lowest rank to the earliest record.&amp;nbsp;The&amp;nbsp;array dimension (100)&amp;nbsp;should not be&amp;nbsp;smaller than the number of records for a single ID, as&amp;nbsp;you appeared to have one record per&amp;nbsp;ID and YEAR, I assumed that 100&amp;nbsp;was a safe value. I added the possibility of zeros,&amp;nbsp;always giving&amp;nbsp;a rank of 0. You may want to take missing values into account also (I would suggest giving them a missing rank, currently they are getting NPOS+N0-100).&lt;/P&gt;</description>
    <pubDate>Wed, 04 Oct 2017 10:58:19 GMT</pubDate>
    <dc:creator>s_lassen</dc:creator>
    <dc:date>2017-10-04T10:58:19Z</dc:date>
    <item>
      <title>Allocating numbers from "-n" to "+n" while ranking a variable by group</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Allocating-numbers-from-quot-n-quot-to-quot-n-quot-while-ranking/m-p/397652#M278320</link>
      <description>&lt;P&gt;Hi&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I have a dataset with millions of observations for several IDs. I have given a small example below to narate the issue.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Say, I have following dataset where each ID has observations (sorted) ranging&amp;nbsp;from negative to positive values. I need to allocate ranks (smallest to largest) to these observations "By ID", the ranks must be ranging from -n to +n as shown below.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data have; 
  input id year ret;
  datalines;
45  2005  -0.30
45  2006   0.28
45  2007  -0.08
48  2011  -0.01
48  2012   0.78
48  2013   0.54
49  2007   0.15
49  2008  -0.06
49  2009   0.3
49  2010  -0.06
;
run;
proc sort data=have;
by id ret;
run;&lt;BR /&gt;&lt;/CODE&gt;&lt;/PRE&gt;&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data want; 
  input id year ret counter;
  datalines;
45  2005  -0.30    -2
45  2007  -0.08    -1
45  2006   0.28     1
48  2011  -0.01    -1
48  2013   0.54     1
48  2012   0.78     2
49  2008  -0.06    -2
49  2010  -0.06    -1
49  2007   0.15     1&lt;BR /&gt;49  2009   0.3      2&lt;BR /&gt;;
run;&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;Please help me fin finding codes for:&lt;/P&gt;&lt;P&gt;1- Finding number of negative and positive values in each ID.&lt;/P&gt;&lt;P&gt;2- Allocating rank counter from smallest to largest.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Thanks.&lt;/P&gt;</description>
      <pubDate>Thu, 21 Sep 2017 04:21:45 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Allocating-numbers-from-quot-n-quot-to-quot-n-quot-while-ranking/m-p/397652#M278320</guid>
      <dc:creator>Saba1</dc:creator>
      <dc:date>2017-09-21T04:21:45Z</dc:date>
    </item>
    <item>
      <title>Re: Allocating numbers from "-n" to "+n" while ranking a variable by group</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Allocating-numbers-from-quot-n-quot-to-quot-n-quot-while-ranking/m-p/397653#M278321</link>
      <description>&lt;P&gt;This looks like a homework assignment.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Why don't you provide a sample dataset and code that you have tried to use, so we can help you figure things out.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;But as an operational problem, it looks like you could&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;sort the data smallest to largest value of some variable for each id&lt;/LI&gt;
&lt;LI&gt;For each id&lt;/LI&gt;
&lt;OL&gt;
&lt;LI&gt;count the number of negatives (N_Neg).&lt;/LI&gt;
&lt;LI&gt;Using that count, assign the "negative ranks" sequentially from -N_neg to -1&lt;/LI&gt;
&lt;LI&gt;For positives assign ranks sequentially starting at 1&lt;/LI&gt;
&lt;/OL&gt;
&lt;/OL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Thu, 21 Sep 2017 00:35:09 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Allocating-numbers-from-quot-n-quot-to-quot-n-quot-while-ranking/m-p/397653#M278321</guid>
      <dc:creator>mkeintz</dc:creator>
      <dc:date>2017-09-21T00:35:09Z</dc:date>
    </item>
    <item>
      <title>Re: Allocating numbers from "-n" to "+n" while ranking a variable by group</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Allocating-numbers-from-quot-n-quot-to-quot-n-quot-while-ranking/m-p/397654#M278322</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;can you provide the code please?&lt;/P&gt;</description>
      <pubDate>Thu, 21 Sep 2017 01:06:30 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Allocating-numbers-from-quot-n-quot-to-quot-n-quot-while-ranking/m-p/397654#M278322</guid>
      <dc:creator>Saba1</dc:creator>
      <dc:date>2017-09-21T01:06:30Z</dc:date>
    </item>
    <item>
      <title>Re: Allocating numbers from "-n" to "+n" while ranking a variable by group</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Allocating-numbers-from-quot-n-quot-to-quot-n-quot-while-ranking/m-p/397659#M278323</link>
      <description>&lt;P&gt;While I would normally program this just the way&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/31461"&gt;@mkeintz&lt;/a&gt;&amp;nbsp;suggested, it sounds like that's difficult for you. &amp;nbsp;So I'll present an easier approach:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;proc sort data=have out=negatives;&lt;/P&gt;
&lt;P&gt;by id descending ret;&lt;/P&gt;
&lt;P&gt;where ret &amp;lt; 0;&lt;/P&gt;
&lt;P&gt;run;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;proc sort data=have out=positives;&lt;/P&gt;
&lt;P&gt;by id ret;&lt;/P&gt;
&lt;P&gt;where ret &amp;gt; 0;&lt;/P&gt;
&lt;P&gt;run;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;data negatives;&lt;/P&gt;
&lt;P&gt;set negatives;&lt;/P&gt;
&lt;P&gt;by id;&lt;/P&gt;
&lt;P&gt;if first.id then counter=-1;&lt;/P&gt;
&lt;P&gt;else counter + (-1);&lt;/P&gt;
&lt;P&gt;run;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;data positives;&lt;/P&gt;
&lt;P&gt;set positives;&lt;/P&gt;
&lt;P&gt;by id;&lt;/P&gt;
&lt;P&gt;if first.id then counter=1;&lt;/P&gt;
&lt;P&gt;else counter + 1;&lt;/P&gt;
&lt;P&gt;run;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;data want;&lt;/P&gt;
&lt;P&gt;set negatives positives;&lt;/P&gt;
&lt;P&gt;by id;&lt;/P&gt;
&lt;P&gt;run;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The order won't be quite right, but you can fix that:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;proc sort data=want;&lt;/P&gt;
&lt;P&gt;by id counter;&lt;/P&gt;
&lt;P&gt;run;&lt;/P&gt;</description>
      <pubDate>Thu, 21 Sep 2017 01:17:40 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Allocating-numbers-from-quot-n-quot-to-quot-n-quot-while-ranking/m-p/397659#M278323</guid>
      <dc:creator>Astounding</dc:creator>
      <dc:date>2017-09-21T01:17:40Z</dc:date>
    </item>
    <item>
      <title>Re: Allocating numbers from "-n" to "+n" while ranking a variable by group</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Allocating-numbers-from-quot-n-quot-to-quot-n-quot-while-ranking/m-p/397666#M278324</link>
      <description>&lt;P&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/4954"&gt;@Astounding&lt;/a&gt;&amp;nbsp;Thank you so much for your detailed reply. This is quite helpful.&lt;/P&gt;</description>
      <pubDate>Thu, 21 Sep 2017 01:38:46 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Allocating-numbers-from-quot-n-quot-to-quot-n-quot-while-ranking/m-p/397666#M278324</guid>
      <dc:creator>Saba1</dc:creator>
      <dc:date>2017-09-21T01:38:46Z</dc:date>
    </item>
    <item>
      <title>Re: Allocating numbers from "-n" to "+n" while ranking a variable by group</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Allocating-numbers-from-quot-n-quot-to-quot-n-quot-while-ranking/m-p/397668#M278325</link>
      <description>&lt;P&gt;Try this.....&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data NEG WANT;
  set HAVE;
if ret&amp;lt;0 then output NEG;
  else output WANT;
run;

proc sort data=neg;
  by ID descending RET;
run;

data NEG;
  set NEG;
by id;
if first.id then ctr=.;
ctr+1;
run;

proc sql;
  update NEG
  SET CTR=CTR*-1;
quit;


proc sort data=want;
  by id ret;
run;

data want;
  set want;
by id;
if first.id then ctr=.;
ctr+1;
run;

proc append base=want data=neg force;
 run;

proc sort data=want;
  by id ctr;
run;&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;Hope this helps.&lt;/P&gt;</description>
      <pubDate>Thu, 21 Sep 2017 01:45:56 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Allocating-numbers-from-quot-n-quot-to-quot-n-quot-while-ranking/m-p/397668#M278325</guid>
      <dc:creator>ShiroAmada</dc:creator>
      <dc:date>2017-09-21T01:45:56Z</dc:date>
    </item>
    <item>
      <title>Re: Allocating numbers from "-n" to "+n" while ranking a variable by group</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Allocating-numbers-from-quot-n-quot-to-quot-n-quot-while-ranking/m-p/397681#M278326</link>
      <description>&lt;P&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/160362"&gt;@ShiroAmada&lt;/a&gt;&amp;nbsp;Thanks a lot. Really useful.&lt;/P&gt;</description>
      <pubDate>Thu, 21 Sep 2017 03:19:48 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Allocating-numbers-from-quot-n-quot-to-quot-n-quot-while-ranking/m-p/397681#M278326</guid>
      <dc:creator>Saba1</dc:creator>
      <dc:date>2017-09-21T03:19:48Z</dc:date>
    </item>
    <item>
      <title>Re: Allocating numbers from "-n" to "+n" while ranking a variable by group</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Allocating-numbers-from-quot-n-quot-to-quot-n-quot-while-ranking/m-p/400905#M278327</link>
      <description>&lt;P&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/166516"&gt;@Saba1&lt;/a&gt;&lt;/P&gt;&lt;P&gt;As you state that your data has millions of observations, it may be more efficient if you can do the calculation without sorting (assuming that you initial data is sorted by ID and YEAR):&lt;/P&gt;&lt;PRE&gt;data want;
  array values(100) 8 _temporary_;
  npos=0;
  nneg=0;
  n0=0;
  do _N_=1 by 1 until(last.id);
    set have(keep=id ret);
    by id;
    values(_N_)=ret;
    if ret&amp;lt;0 then
      nneg+1; /* number of negative values */
    else if ret&amp;gt;0 then
      npos+1; /* number of positive values */
    else
      n0+1; /* number of zeroes */
    end;
  call sortn(of values(*));
  do until(last.id);
    set have;
    by id;
    _N_=whichn(ret,of values(*));
    if ret=0 then
      rank=0;
    else if ret&amp;lt;0 then
      rank=_N_-100+npos+n0-1;
    else
      rank=_N_-100+npos;
    values(_N_)=.; /* set missing, so that next record with same value gets next rank */
    output;
    end;
run;

&lt;/PRE&gt;&lt;P&gt;If two years have the same ID and RET value, the program assigns the lowest rank to the earliest record.&amp;nbsp;The&amp;nbsp;array dimension (100)&amp;nbsp;should not be&amp;nbsp;smaller than the number of records for a single ID, as&amp;nbsp;you appeared to have one record per&amp;nbsp;ID and YEAR, I assumed that 100&amp;nbsp;was a safe value. I added the possibility of zeros,&amp;nbsp;always giving&amp;nbsp;a rank of 0. You may want to take missing values into account also (I would suggest giving them a missing rank, currently they are getting NPOS+N0-100).&lt;/P&gt;</description>
      <pubDate>Wed, 04 Oct 2017 10:58:19 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Allocating-numbers-from-quot-n-quot-to-quot-n-quot-while-ranking/m-p/400905#M278327</guid>
      <dc:creator>s_lassen</dc:creator>
      <dc:date>2017-10-04T10:58:19Z</dc:date>
    </item>
  </channel>
</rss>

