<?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 second last observation in a dataset in SAS Programming</title>
    <link>https://communities.sas.com/t5/SAS-Programming/second-last-observation-in-a-dataset/m-p/921578#M362916</link>
    <description>&lt;P&gt;Hi All,&lt;/P&gt;
&lt;P&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; I have the following dataset:&lt;/P&gt;
&lt;PRE&gt;data have;
input id name $ score;
datalines;
1  David    45
1  David    74
2  Sam      45
2  Ram      54
3  Bane     87
3  Mary     92
3  Bane     87
4  Dane     23
5  Jenny    87
5  Ken      87
6  Simran1  63
6  Simran2  65
6  Simran3  53
6  Simran4  73
6  Simran5  33
6  Simran6  45
8  Priya    72
;
run;&lt;/PRE&gt;
&lt;P&gt;I want the following output:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;Id  Name    Score&lt;BR /&gt;1  David    45
2  Sam      45
3  Mary     92
4  Dane     23
5  Jenny    87
6  Simran5  33
8  Priya    72
&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I have tried the following, but it's not working:&lt;/P&gt;
&lt;PRE&gt;proc sort data=have out=have_srt;&lt;BR /&gt;by id;&lt;BR /&gt;run;&lt;BR /&gt;&lt;BR /&gt;data want;
	set have_srt;
	by id;

	if first.id then start=_n_;
	retain start;

	if last.id then do point=max(Start, _n_ -2) to _n_;
		set have_srt point=point;
		output;
	end;
	drop start;
run;&lt;/PRE&gt;
&lt;P&gt;Please, help.&amp;nbsp;&lt;/P&gt;</description>
    <pubDate>Sat, 23 Mar 2024 09:44:13 GMT</pubDate>
    <dc:creator>Moksha</dc:creator>
    <dc:date>2024-03-23T09:44:13Z</dc:date>
    <item>
      <title>second last observation in a dataset</title>
      <link>https://communities.sas.com/t5/SAS-Programming/second-last-observation-in-a-dataset/m-p/921578#M362916</link>
      <description>&lt;P&gt;Hi All,&lt;/P&gt;
&lt;P&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; I have the following dataset:&lt;/P&gt;
&lt;PRE&gt;data have;
input id name $ score;
datalines;
1  David    45
1  David    74
2  Sam      45
2  Ram      54
3  Bane     87
3  Mary     92
3  Bane     87
4  Dane     23
5  Jenny    87
5  Ken      87
6  Simran1  63
6  Simran2  65
6  Simran3  53
6  Simran4  73
6  Simran5  33
6  Simran6  45
8  Priya    72
;
run;&lt;/PRE&gt;
&lt;P&gt;I want the following output:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;Id  Name    Score&lt;BR /&gt;1  David    45
2  Sam      45
3  Mary     92
4  Dane     23
5  Jenny    87
6  Simran5  33
8  Priya    72
&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I have tried the following, but it's not working:&lt;/P&gt;
&lt;PRE&gt;proc sort data=have out=have_srt;&lt;BR /&gt;by id;&lt;BR /&gt;run;&lt;BR /&gt;&lt;BR /&gt;data want;
	set have_srt;
	by id;

	if first.id then start=_n_;
	retain start;

	if last.id then do point=max(Start, _n_ -2) to _n_;
		set have_srt point=point;
		output;
	end;
	drop start;
run;&lt;/PRE&gt;
&lt;P&gt;Please, help.&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sat, 23 Mar 2024 09:44:13 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/second-last-observation-in-a-dataset/m-p/921578#M362916</guid>
      <dc:creator>Moksha</dc:creator>
      <dc:date>2024-03-23T09:44:13Z</dc:date>
    </item>
    <item>
      <title>Re: second last observation in a dataset</title>
      <link>https://communities.sas.com/t5/SAS-Programming/second-last-observation-in-a-dataset/m-p/921579#M362917</link>
      <description>&lt;P&gt;Hello&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/439180"&gt;@Moksha&lt;/a&gt;,&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Good idea to use the POINT= option. Here is a similar approach:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data want;
set have;
by id;
if last.id then do;
  if first.id then output;
  else do;
    _n_+(-1);
    set have point=_n_;
    output;
  end;
end;
run;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;The same result can be achieved with this simpler, but likely less efficient code:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data want;
set have;
by id;
if last.id then do;
  _n_+(first.id-1);
  set have point=_n_;
  output;
end;
run;&lt;/CODE&gt;&lt;/PRE&gt;</description>
      <pubDate>Sat, 23 Mar 2024 10:06:17 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/second-last-observation-in-a-dataset/m-p/921579#M362917</guid>
      <dc:creator>FreelanceReinh</dc:creator>
      <dc:date>2024-03-23T10:06:17Z</dc:date>
    </item>
    <item>
      <title>Re: second last observation in a dataset</title>
      <link>https://communities.sas.com/t5/SAS-Programming/second-last-observation-in-a-dataset/m-p/921580#M362918</link>
      <description>&lt;P&gt;Thank you very much&amp;nbsp;&lt;SPAN&gt;&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/32733"&gt;@FreelanceReinh&lt;/a&gt;&amp;nbsp;. It's very helpful and solved the problem.&lt;/SPAN&gt;&lt;/P&gt;</description>
      <pubDate>Sat, 23 Mar 2024 10:12:21 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/second-last-observation-in-a-dataset/m-p/921580#M362918</guid>
      <dc:creator>Moksha</dc:creator>
      <dc:date>2024-03-23T10:12:21Z</dc:date>
    </item>
    <item>
      <title>Re: second last observation in a dataset</title>
      <link>https://communities.sas.com/t5/SAS-Programming/second-last-observation-in-a-dataset/m-p/921581#M362919</link>
      <description>&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data have;
input id name $ score;
datalines;
1  David    45
1  David    74
2  Sam      45
2  Ram      54
3  Bane     87
3  Mary     92
3  Bane     87
4  Dane     23
5  Jenny    87
5  Ken      87
6  Simran1  63
6  Simran2  65
6  Simran3  53
6  Simran4  73
6  Simran5  33
6  Simran6  45
8  Priya    72
;
run;
data want;
 merge have have(firstobs=2 keep=id rename=(id=_id)) have(firstobs=3 keep=id rename=(id=__id));
 if (id=_id and id ne __id) or (id ne _id and id ne lag(id));
 drop _id __id;
run;&lt;/CODE&gt;&lt;/PRE&gt;</description>
      <pubDate>Sat, 23 Mar 2024 10:18:37 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/second-last-observation-in-a-dataset/m-p/921581#M362919</guid>
      <dc:creator>Ksharp</dc:creator>
      <dc:date>2024-03-23T10:18:37Z</dc:date>
    </item>
    <item>
      <title>Re: second last observation in a dataset</title>
      <link>https://communities.sas.com/t5/SAS-Programming/second-last-observation-in-a-dataset/m-p/921582#M362920</link>
      <description>&lt;P&gt;I like the use of merge and the &lt;EM&gt;&lt;STRONG&gt;firstobs=&lt;/STRONG&gt;&lt;/EM&gt; dataset name parameter proposed by&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/18408"&gt;@Ksharp&lt;/a&gt;&amp;nbsp;.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Here's a minor tweak (&lt;EM&gt;&lt;STRONG&gt;firstobs=3&lt;/STRONG&gt;&lt;/EM&gt;&amp;nbsp;only) to simplify a bit further:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data have;
input id name $ score ;
datalines;
1  David    45
1  David    74
2  Sam      45
2  Ram      54
3  Bane     87
3  Mary     92
3  Bane     87
4  Dane     23
5  Jenny    87
5  Ken      87
6  Simran1  63
6  Simran2  65
6  Simran3  53
6  Simran4  73
6  Simran5  33
6  Simran6  45
8  Priya    72
;
run;
data want (drop=nxt:);
  set have ;
  by id;
  merge have (keep=id)  have (firstobs=3 keep=id rename=(id=nxt2_id));

  if (first.id=1 and last.id=1) or (last.id=0 and id^=nxt2_id);
run;&lt;/CODE&gt;&lt;/PRE&gt;</description>
      <pubDate>Sat, 23 Mar 2024 11:51:29 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/second-last-observation-in-a-dataset/m-p/921582#M362920</guid>
      <dc:creator>mkeintz</dc:creator>
      <dc:date>2024-03-23T11:51:29Z</dc:date>
    </item>
    <item>
      <title>Re: second last observation in a dataset</title>
      <link>https://communities.sas.com/t5/SAS-Programming/second-last-observation-in-a-dataset/m-p/921583#M362921</link>
      <description>&lt;P&gt;Thank you&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/18408"&gt;@Ksharp&lt;/a&gt;&amp;nbsp;, it's very helpful.&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sat, 23 Mar 2024 12:07:28 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/second-last-observation-in-a-dataset/m-p/921583#M362921</guid>
      <dc:creator>Moksha</dc:creator>
      <dc:date>2024-03-23T12:07:28Z</dc:date>
    </item>
    <item>
      <title>Re: second last observation in a dataset</title>
      <link>https://communities.sas.com/t5/SAS-Programming/second-last-observation-in-a-dataset/m-p/921584#M362922</link>
      <description>&lt;P&gt;Thank you&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/31461"&gt;@mkeintz&lt;/a&gt;&amp;nbsp;. It's very helpful.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I thank all, I got to learn here different methods.&lt;/P&gt;</description>
      <pubDate>Sat, 23 Mar 2024 12:08:47 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/second-last-observation-in-a-dataset/m-p/921584#M362922</guid>
      <dc:creator>Moksha</dc:creator>
      <dc:date>2024-03-23T12:08:47Z</dc:date>
    </item>
    <item>
      <title>Re: second last observation in a dataset</title>
      <link>https://communities.sas.com/t5/SAS-Programming/second-last-observation-in-a-dataset/m-p/921595#M362924</link>
      <description>&lt;P&gt;Hey&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/439180"&gt;@Moksha&lt;/a&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;You already have a nice set of solutions, but just for fun, two more:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;one, that uses hash table and backward-reading of data (this one allows to replace 2nd-last with 3rd-last, 4th-last, etc. by setting the WHICH variable):&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data want;
  which=2; /* which "n last" from the group */
  drop which;

  /* hash table to store the list of observations numbers */
  declare hash H(ordered:"A"); /* to keep order of IDs */
    H.defineKey("id");
    H.defineData("p", "_N_");
    H.defineDone();
  declare hiter I("H");

  /* read data backward and get obs number for "n last" from the group */
  do point=nobs to 1 by -1; 
    set have nobs=nobs point=point;

    if H.find() then _N_=1; /* counter of obs in a group (counted from the last one) */
                else _N_+1;

    if _N_ &amp;lt;= which then /* take the closes to the one you want, e.g., if only 2 obs in group will select 2nd, etc.*/
      do;
        p=point; /* obs to select */
        H.replace();
      end;
  end;
  
  /* loops over selected observations */
  do while(I.next()=0); 
    set have point=p;
    output;
  end;
stop;
run;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;second, that uses backward reading (result is reversed):&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data want;
  do point=nobs to 1 by -1;
    set have point=point nobs=nobs;
    output;
  end;
  stop;
data want;
  set want;
  by descending ID;
  if first.ID then second=0;
  second+1;
  if first.ID*last.ID OR second=2 then output;
  drop second;
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;Bart&lt;/P&gt;</description>
      <pubDate>Sat, 23 Mar 2024 17:07:50 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/second-last-observation-in-a-dataset/m-p/921595#M362924</guid>
      <dc:creator>yabwon</dc:creator>
      <dc:date>2024-03-23T17:07:50Z</dc:date>
    </item>
    <item>
      <title>Re: second last observation in a dataset</title>
      <link>https://communities.sas.com/t5/SAS-Programming/second-last-observation-in-a-dataset/m-p/921604#M362925</link>
      <description>&lt;P&gt;This is a general program that provides for any offset (macrovar OFL) from the last observation:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;%let OFL=3;   /*Offset from last 0=last, 1=last but 1, etc. */
data want (drop=_: label="Nearest Obs to &amp;amp;OFL before last");
  set have (in=firstpass)  have (in=secondpass);
  by id;
  if first.id then call missing (_n1, _n2);
  _n1+firstpass;    *Count firstpass obs for this ID;
  _n2+secondpass;

  if dif(secondpass)=1 then _n1=max(1,_n1-&amp;amp;ofl);  *Reset _N1 to target obs *;
  if secondpass=1 and _n2=_n1;
run;
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;You control the desired offset value with the&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;&lt;STRONG&gt;&amp;nbsp; &amp;nbsp; %LET OFL=value-goes-here ;&lt;/STRONG&gt;&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;assignment of a value to macrovar OFL.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;&lt;STRONG&gt;The DIF(secondpass) =1&lt;/STRONG&gt;&lt;/EM&gt; condition (where dif(secondpass) is defined as&lt;STRONG&gt; secondpass-lag(secondpass)&lt;/STRONG&gt; is a way to identify the start of the second pass through each ID.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Edit note:&amp;nbsp; Thanks to&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/32733"&gt;@FreelanceReinh&lt;/a&gt;, I modified the &lt;STRONG&gt;"if dif(secondpass)=1 ..."&lt;/STRONG&gt; statement, so that in the event of an underpopulated ID, the target obs is the first (I had it as the last) obs in the ID group.&lt;/P&gt;</description>
      <pubDate>Mon, 25 Mar 2024 17:25:35 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/second-last-observation-in-a-dataset/m-p/921604#M362925</guid>
      <dc:creator>mkeintz</dc:creator>
      <dc:date>2024-03-25T17:25:35Z</dc:date>
    </item>
    <item>
      <title>Re: second last observation in a dataset</title>
      <link>https://communities.sas.com/t5/SAS-Programming/second-last-observation-in-a-dataset/m-p/921606#M362926</link>
      <description>&lt;P&gt;Another "self-interleaving" masterclass. Kudos,&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/31461"&gt;@mkeintz&lt;/a&gt;!&lt;/P&gt;
&lt;P&gt;After analyzing the clever logic, I would have expected &lt;FONT face="courier new,courier"&gt;1&lt;/FONT&gt;, not &lt;FONT face="courier new,courier"&gt;_n1&lt;/FONT&gt;, in the second argument of the IFN function or&lt;/P&gt;
&lt;PRE&gt;&lt;FONT color="#999999"&gt;if dif(secondpass)=1 then _n1=&lt;FONT color="#000000"&gt;&lt;STRONG&gt;max(1,_n1-&amp;amp;ofl)&lt;/STRONG&gt;&lt;/FONT&gt;;  *Reset N1 to target obs *;&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;for short?&lt;/P&gt;</description>
      <pubDate>Sat, 23 Mar 2024 23:23:26 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/second-last-observation-in-a-dataset/m-p/921606#M362926</guid>
      <dc:creator>FreelanceReinh</dc:creator>
      <dc:date>2024-03-23T23:23:26Z</dc:date>
    </item>
    <item>
      <title>Re: second last observation in a dataset</title>
      <link>https://communities.sas.com/t5/SAS-Programming/second-last-observation-in-a-dataset/m-p/921608#M362927</link>
      <description>&lt;BLOCKQUOTE&gt;&lt;HR /&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/32733"&gt;@FreelanceReinh&lt;/a&gt;&amp;nbsp;wrote:&lt;BR /&gt;
&lt;P&gt;Another "self-interleaving" masterclass. Kudos,&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/31461"&gt;@mkeintz&lt;/a&gt;!&lt;/P&gt;
&lt;P&gt;After analyzing the clever logic, I would have expected &lt;FONT face="courier new,courier"&gt;1&lt;/FONT&gt;, not &lt;FONT face="courier new,courier"&gt;_n1&lt;/FONT&gt;, in the second argument of the IFN function or&lt;/P&gt;
&lt;PRE&gt;&lt;FONT color="#999999"&gt;if dif(secondpass)=1 then _n1=&lt;FONT color="#000000"&gt;&lt;STRONG&gt;max(1,_n1-&amp;amp;ofl)&lt;/STRONG&gt;&lt;/FONT&gt;;  *Reset N1 to target obs *;&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;for short?&lt;/P&gt;
&lt;HR /&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;I think you're right.&amp;nbsp; I think I misinterpreted what the OP wants when the ID is underpopulated.&amp;nbsp; They want the first, not the last obs.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I'm going to change my response.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sun, 24 Mar 2024 01:55:52 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/second-last-observation-in-a-dataset/m-p/921608#M362927</guid>
      <dc:creator>mkeintz</dc:creator>
      <dc:date>2024-03-24T01:55:52Z</dc:date>
    </item>
  </channel>
</rss>

