<?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: RETAIN +FIRST in SAS Programming</title>
    <link>https://communities.sas.com/t5/SAS-Programming/RETAIN-FIRST/m-p/957235#M373697</link>
    <description>&lt;P&gt;I think the confusion is coming from the (&lt;STRONG&gt;mistaken&lt;/STRONG&gt;) idea that, e.g., FIRST.VAR is the first *value* of VAR within a group -- so for example, if the first value of SEX is 1, then first.VAR would be equal to 1 when var=sex.&amp;nbsp; And if the first value of age were 38, then first.VAR would equal 38 when var=age.&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;But that is &lt;STRONG&gt;NOT&lt;/STRONG&gt; what first.VAR or last.VAR are doing at all.&amp;nbsp; first.VAR is simply an &lt;EM&gt;indicator of whether or not we are at the first row&lt;/EM&gt; within that BY group -- 1 if true, 0 if false.&amp;nbsp; So first.VAR &lt;EM&gt;is a separate variable&lt;/EM&gt;.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;It is also tied to the BY statement -- first.&amp;lt;variable&amp;gt; and last.&amp;lt;variable&amp;gt; do not exist if you do not have a corresponding BY statement.&amp;nbsp; For example, let's say you have the following dataset, which we sort by state, and within state, by year, and within year, by month.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;That allows us to have a BY statement that says&amp;nbsp;&amp;nbsp;&lt;STRONG&gt;&lt;FONT face="courier new,courier"&gt;BY state year month;&lt;/FONT&gt;&lt;/STRONG&gt;&amp;nbsp; (order has to match the sorting).&amp;nbsp; In order to see the values of first.state, first.year and first.month, we're just saving them in permanent variables (normally, there's not a need to do this - you can just use the first. or last. variables directly and be done with them).&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data test;
infile cards dsd truncover firstobs=1 dlm=',';
length state $2 year month 3 rate 8;
input state year month rate;
cards;
NY,2020,1,0.37
NY,2020,2,0.39
NY,2020,3,0.32
NY,2020,4,0.36
NY,2021,1,0.09
NY,2021,2,0.14
NY,2021,3,0.14
NY,2021,4,0.20
MA,2020,1,0.29
MA,2020,2,0.41
MA,2020,3,0.35
MA,2020,4,0.33
MA,2021,1,0.18
MA,2021,2,0.17
MA,2021,3,0.22
MA,2021,4,0.27
;
run;

proc sort data=test; by state year month; run;

data test2;
set test;
by state year month;
is_first_dot_state=first.state;
is_first_dot_year=first.year;
is_first_dot_month=first.month;
run;

proc print data=test2 noobs; run;
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Result is the following:&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="quickbluefish_1-1737836904357.png" style="width: 400px;"&gt;&lt;img src="https://communities.sas.com/t5/image/serverpage/image-id/104001iFA20C187F314E0FB/image-size/medium?v=v2&amp;amp;px=400" role="button" title="quickbluefish_1-1737836904357.png" alt="quickbluefish_1-1737836904357.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
    <pubDate>Sat, 25 Jan 2025 20:29:21 GMT</pubDate>
    <dc:creator>quickbluefish</dc:creator>
    <dc:date>2025-01-25T20:29:21Z</dc:date>
    <item>
      <title>RETAIN +FIRST</title>
      <link>https://communities.sas.com/t5/SAS-Programming/RETAIN-FIRST/m-p/957218#M373688</link>
      <description>&lt;P&gt;Hello&lt;/P&gt;
&lt;P&gt;I want to create serial number in such way that all rows for same VAR get same serial number.&lt;/P&gt;
&lt;P&gt;This code is working 100%&lt;/P&gt;
&lt;P&gt;However, I dont understand how SAS calculate it and how it works.&lt;/P&gt;
&lt;P&gt;Is it possible to see the SAS iterations step by step to understand how sas perform the calculation ?&lt;/P&gt;
&lt;P&gt;As I understand&amp;nbsp; in first line of sex the value is 1&amp;nbsp; (0+1)&lt;/P&gt;
&lt;P&gt;then I dont understand why second line of sex&amp;nbsp; is also 1 because&amp;nbsp; &amp;nbsp;1+1 is 2&lt;/P&gt;
&lt;P&gt;I also dont undersdtand why first row of VAR age&amp;nbsp; is 2?&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;Data have;
input VAR $ category  estimate;
cards;
sex 1 0.7257
sex 2 0
age 1 0.8356
age 2 0.6093
age 3 0
;
run;
proc sort data=have;by  VAR category;Run;
Data want;
set have;
by VAR;
retain n  0;
if first.VAR then n=n+1;;
Run;
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sat, 25 Jan 2025 08:02:37 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/RETAIN-FIRST/m-p/957218#M373688</guid>
      <dc:creator>Ronein</dc:creator>
      <dc:date>2025-01-25T08:02:37Z</dc:date>
    </item>
    <item>
      <title>Re: RETAIN +FIRST</title>
      <link>https://communities.sas.com/t5/SAS-Programming/RETAIN-FIRST/m-p/957223#M373691</link>
      <description>&lt;P&gt;Below modified code shows you for which rows first.var returns 1. I hope this will help you understand the result you're getting.&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;Data want;
	set have;
	by VAR category;
	retain n 0;
	if first.VAR then n=n+1;
	first_var_flg=first.var;
	first_cat_flg=first.category;
Run;

proc print data=want;
run;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Patrick_0-1737806162555.png" style="width: 400px;"&gt;&lt;img src="https://communities.sas.com/t5/image/serverpage/image-id/103997i2A6C9E38801B9176/image-size/medium?v=v2&amp;amp;px=400" role="button" title="Patrick_0-1737806162555.png" alt="Patrick_0-1737806162555.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;Is it possible to see the SAS iterations step by step to understand how sas perform the calculation ?&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;P&gt;There is a &lt;A href="https://documentation.sas.com/doc/en/egdoccdc/8.2/egug/n0osho4x42b0pkn17yb7e3bj5hjq.htm" target="_self"&gt;data step debugger&lt;/A&gt;&amp;nbsp;that works with "PC SAS" that's now also available for recent SAS EG and SAS Studio clients. I haven't used it often myself so can't tell how useful it is.&lt;/P&gt;</description>
      <pubDate>Sat, 25 Jan 2025 12:06:11 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/RETAIN-FIRST/m-p/957223#M373691</guid>
      <dc:creator>Patrick</dc:creator>
      <dc:date>2025-01-25T12:06:11Z</dc:date>
    </item>
    <item>
      <title>Re: RETAIN +FIRST</title>
      <link>https://communities.sas.com/t5/SAS-Programming/RETAIN-FIRST/m-p/957225#M373692</link>
      <description>&lt;P&gt;Yes, and since&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier"&gt;first.&amp;lt;your variable name&amp;gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;is just a temporary (meaning, it only exists during the execution of the current data step) 0/1 variable, you can simply add its value to n each time and get the same result:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data want;
set have;
by VAR;
n+first.var;
run;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;For every row, it's adding either a 0 or a 1 to the current value of n.&amp;nbsp; And because we're using the syntax like "n+1" instead of "n=n+1", the variable n is automatically retained.&amp;nbsp;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sat, 25 Jan 2025 13:40:08 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/RETAIN-FIRST/m-p/957225#M373692</guid>
      <dc:creator>quickbluefish</dc:creator>
      <dc:date>2025-01-25T13:40:08Z</dc:date>
    </item>
    <item>
      <title>Re: RETAIN +FIRST</title>
      <link>https://communities.sas.com/t5/SAS-Programming/RETAIN-FIRST/m-p/957231#M373695</link>
      <description>&lt;BLOCKQUOTE&gt;&lt;HR /&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/159549"&gt;@Ronein&lt;/a&gt;&amp;nbsp;wrote:&lt;BR /&gt;
&lt;P&gt;As I understand&amp;nbsp; in first line of sex the value is 1&amp;nbsp; (0+1)&lt;/P&gt;
&lt;P&gt;then I dont understand why second line of sex&amp;nbsp; is also 1 because&amp;nbsp; &amp;nbsp;1+1 is 2&lt;/P&gt;
&lt;P&gt;I also dont undersdtand why first row of VAR age&amp;nbsp; is 2?&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;HR /&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Read this line out loud:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;if first.VAR then n=n+1;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;If first dot var then n gets n+1.&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;P&gt;That code adds one to N only on the FIRST observation for a particular value of VAR.&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;So obviously the value of N does not change on the SECOND observation with VAR=SEX but it will change on the FIRST observation with VAR=AGE.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Note if you run your code you should get N=1 when VAR=age and N=2 when VAR=sex because age comes before sex in alphabetical order.&amp;nbsp; If you are seeing sex before age then check the actual values of the variables.&amp;nbsp; Perhaps you have SEX and age?&amp;nbsp; Lowercase letters sort after uppercase letters.&amp;nbsp; Or perhaps you have " sex" and "age".&amp;nbsp; Space sorts before letters.&lt;/P&gt;</description>
      <pubDate>Sat, 25 Jan 2025 18:19:56 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/RETAIN-FIRST/m-p/957231#M373695</guid>
      <dc:creator>Tom</dc:creator>
      <dc:date>2025-01-25T18:19:56Z</dc:date>
    </item>
    <item>
      <title>Re: RETAIN +FIRST</title>
      <link>https://communities.sas.com/t5/SAS-Programming/RETAIN-FIRST/m-p/957235#M373697</link>
      <description>&lt;P&gt;I think the confusion is coming from the (&lt;STRONG&gt;mistaken&lt;/STRONG&gt;) idea that, e.g., FIRST.VAR is the first *value* of VAR within a group -- so for example, if the first value of SEX is 1, then first.VAR would be equal to 1 when var=sex.&amp;nbsp; And if the first value of age were 38, then first.VAR would equal 38 when var=age.&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;But that is &lt;STRONG&gt;NOT&lt;/STRONG&gt; what first.VAR or last.VAR are doing at all.&amp;nbsp; first.VAR is simply an &lt;EM&gt;indicator of whether or not we are at the first row&lt;/EM&gt; within that BY group -- 1 if true, 0 if false.&amp;nbsp; So first.VAR &lt;EM&gt;is a separate variable&lt;/EM&gt;.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;It is also tied to the BY statement -- first.&amp;lt;variable&amp;gt; and last.&amp;lt;variable&amp;gt; do not exist if you do not have a corresponding BY statement.&amp;nbsp; For example, let's say you have the following dataset, which we sort by state, and within state, by year, and within year, by month.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;That allows us to have a BY statement that says&amp;nbsp;&amp;nbsp;&lt;STRONG&gt;&lt;FONT face="courier new,courier"&gt;BY state year month;&lt;/FONT&gt;&lt;/STRONG&gt;&amp;nbsp; (order has to match the sorting).&amp;nbsp; In order to see the values of first.state, first.year and first.month, we're just saving them in permanent variables (normally, there's not a need to do this - you can just use the first. or last. variables directly and be done with them).&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data test;
infile cards dsd truncover firstobs=1 dlm=',';
length state $2 year month 3 rate 8;
input state year month rate;
cards;
NY,2020,1,0.37
NY,2020,2,0.39
NY,2020,3,0.32
NY,2020,4,0.36
NY,2021,1,0.09
NY,2021,2,0.14
NY,2021,3,0.14
NY,2021,4,0.20
MA,2020,1,0.29
MA,2020,2,0.41
MA,2020,3,0.35
MA,2020,4,0.33
MA,2021,1,0.18
MA,2021,2,0.17
MA,2021,3,0.22
MA,2021,4,0.27
;
run;

proc sort data=test; by state year month; run;

data test2;
set test;
by state year month;
is_first_dot_state=first.state;
is_first_dot_year=first.year;
is_first_dot_month=first.month;
run;

proc print data=test2 noobs; run;
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Result is the following:&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="quickbluefish_1-1737836904357.png" style="width: 400px;"&gt;&lt;img src="https://communities.sas.com/t5/image/serverpage/image-id/104001iFA20C187F314E0FB/image-size/medium?v=v2&amp;amp;px=400" role="button" title="quickbluefish_1-1737836904357.png" alt="quickbluefish_1-1737836904357.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sat, 25 Jan 2025 20:29:21 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/RETAIN-FIRST/m-p/957235#M373697</guid>
      <dc:creator>quickbluefish</dc:creator>
      <dc:date>2025-01-25T20:29:21Z</dc:date>
    </item>
  </channel>
</rss>

