<?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: Combine multiple variables into a LAST.ab variable in SAS Programming</title>
    <link>https://communities.sas.com/t5/SAS-Programming/Combine-multiple-variables-into-a-LAST-ab-variable/m-p/68097#M14766</link>
    <description>Oh, just for the fun of discussion, a couple of points.&lt;BR /&gt;
&lt;BR /&gt;
SBB: "- two observations: one for each unique A variable value - oh, by the way, the value of B will be whatever occurred on the last/highest observation of A."&lt;BR /&gt;
&lt;BR /&gt;
Actually the value of B would be the maximum value of B within a given A.  Last.A order is driven by the sort order of B within A.  It will return any old value of C, which is my point.&lt;BR /&gt;
&lt;BR /&gt;
OP: "If I have a dataset with variables a and b and I sort by a then b"&lt;BR /&gt;
&lt;BR /&gt;
with only A and B in the data set.  sorted by A and B  with multiple equivalent values of B within a given A, the statements first.B, last.B, anyold.B would give identical records from A-B pairs.&lt;BR /&gt;
&lt;BR /&gt;
The reason I stress this is that I have seen several programmers write code like this when trying to get the record with the maximum value of B within A and got the result you are talking about instead.  And yes, I can see that the way you are reading the OP could be what he intended, I did not read it that way.&lt;BR /&gt;
&lt;BR /&gt;
Thanks for the discussion.</description>
    <pubDate>Mon, 31 Aug 2009 13:35:12 GMT</pubDate>
    <dc:creator>Flip</dc:creator>
    <dc:date>2009-08-31T13:35:12Z</dc:date>
    <item>
      <title>Combine multiple variables into a LAST.ab variable</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Combine-multiple-variables-into-a-LAST-ab-variable/m-p/68087#M14756</link>
      <description>If I have a dataset with variables a and b and I sort by a then b how do I filter for the last entry of b for each a.  My assumption is that I would have some sort statement like&lt;BR /&gt;
IF LAST.ab;&lt;BR /&gt;
where ab is some sort of cartesian product of a and b.  But I don't know how to do this.  Any thoughts?</description>
      <pubDate>Fri, 28 Aug 2009 14:08:09 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Combine-multiple-variables-into-a-LAST-ab-variable/m-p/68087#M14756</guid>
      <dc:creator>deleted_user</dc:creator>
      <dc:date>2009-08-28T14:08:09Z</dc:date>
    </item>
    <item>
      <title>Re: Combine multiple variables into a LAST.ab variable</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Combine-multiple-variables-into-a-LAST-ab-variable/m-p/68088#M14757</link>
      <description>A DATA step technique using a BY statement combined with IF LAST.&lt;VAR1NAME&gt; AND LAST.&lt;VAR2NAME&gt; would be the technique to use.&lt;BR /&gt;
&lt;BR /&gt;
Search the SAS support &lt;A href="http://support.sas.com/" target="_blank"&gt;http://support.sas.com/&lt;/A&gt;  website - using this Google advanced search argument:&lt;BR /&gt;
&lt;BR /&gt;
&lt;BR /&gt;
sas data step first last processing site:sas.com&lt;BR /&gt;
&lt;BR /&gt;
Scott Barry&lt;BR /&gt;
SBBWorks, Inc.&lt;/VAR2NAME&gt;&lt;/VAR1NAME&gt;</description>
      <pubDate>Fri, 28 Aug 2009 14:18:42 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Combine-multiple-variables-into-a-LAST-ab-variable/m-p/68088#M14757</guid>
      <dc:creator>sbb</dc:creator>
      <dc:date>2009-08-28T14:18:42Z</dc:date>
    </item>
    <item>
      <title>Re: Combine multiple variables into a LAST.ab variable</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Combine-multiple-variables-into-a-LAST-ab-variable/m-p/68089#M14758</link>
      <description>Since you have sorted by a b then the last.a is the record with the highest value of b within a.  So all you need is if last.a</description>
      <pubDate>Fri, 28 Aug 2009 14:38:10 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Combine-multiple-variables-into-a-LAST-ab-variable/m-p/68089#M14758</guid>
      <dc:creator>Flip</dc:creator>
      <dc:date>2009-08-28T14:38:10Z</dc:date>
    </item>
    <item>
      <title>Re: Combine multiple variables into a LAST.ab variable</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Combine-multiple-variables-into-a-LAST-ab-variable/m-p/68090#M14759</link>
      <description>Reading the original post and "...filter for the last entry of b for each a", I would say that the BY statement needs to reflect BY A B;  and thus the IF test would be IF LAST.B  to generate the desired filter logic.&lt;BR /&gt;
&lt;BR /&gt;
Scott Barry&lt;BR /&gt;
SBBWorks, Inc.</description>
      <pubDate>Sat, 29 Aug 2009 15:20:56 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Combine-multiple-variables-into-a-LAST-ab-variable/m-p/68090#M14759</guid>
      <dc:creator>sbb</dc:creator>
      <dc:date>2009-08-29T15:20:56Z</dc:date>
    </item>
    <item>
      <title>Re: Combine multiple variables into a LAST.ab variable</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Combine-multiple-variables-into-a-LAST-ab-variable/m-p/68091#M14760</link>
      <description>Scott;&lt;BR /&gt;
That is a common misconception as to how last. works.  Note the code below.&lt;BR /&gt;
data one;&lt;BR /&gt;
do a = 1 to 5;&lt;BR /&gt;
  do b = 1 to 5;&lt;BR /&gt;
  output;&lt;BR /&gt;
  end;&lt;BR /&gt;
end;&lt;BR /&gt;
run;&lt;BR /&gt;
&lt;BR /&gt;
data two;&lt;BR /&gt;
  set one;&lt;BR /&gt;
  by a b;&lt;BR /&gt;
&lt;BR /&gt;
  la = last.a;&lt;BR /&gt;
  lb = last.b;&lt;BR /&gt;
run;&lt;BR /&gt;
proc print;&lt;BR /&gt;
run;&lt;BR /&gt;
&lt;BR /&gt;
The SAS System                                                                               12:42 Saturday, August 29, 2009   3&lt;BR /&gt;
&lt;BR /&gt;
Obs    a    b    la    lb&lt;BR /&gt;
&lt;BR /&gt;
  1    1    1     0     1&lt;BR /&gt;
  2    1    2     0     1&lt;BR /&gt;
  3    1    3     0     1&lt;BR /&gt;
  4    1    4     0     1&lt;BR /&gt;
  5    1    5     1     1&lt;BR /&gt;
  6    2    1     0     1&lt;BR /&gt;
  7    2    2     0     1&lt;BR /&gt;
  8    2    3     0     1&lt;BR /&gt;
  9    2    4     0     1&lt;BR /&gt;
 10    2    5     1     1&lt;BR /&gt;
 11    3    1     0     1&lt;BR /&gt;
 12    3    2     0     1&lt;BR /&gt;
 13    3    3     0     1&lt;BR /&gt;
 14    3    4     0     1&lt;BR /&gt;
 15    3    5     1     1&lt;BR /&gt;
 16    4    1     0     1&lt;BR /&gt;
 17    4    2     0     1&lt;BR /&gt;
 18    4    3     0     1&lt;BR /&gt;
 19    4    4     0     1&lt;BR /&gt;
 20    4    5     1     1&lt;BR /&gt;
 21    5    1     0     1&lt;BR /&gt;
 22    5    2     0     1&lt;BR /&gt;
 23    5    3     0     1&lt;BR /&gt;
 24    5    4     0     1&lt;BR /&gt;
 25    5    5     1     1&lt;BR /&gt;
&lt;BR /&gt;
Now note that since b is changing, last.b is always true.  In fact last. is only meaningfull if there is a sort order below it.  So since each group of A is sorted by B, the way to find the highest value of B within A is to take last.A.&lt;BR /&gt;
&lt;BR /&gt;
Flip</description>
      <pubDate>Sat, 29 Aug 2009 16:55:49 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Combine-multiple-variables-into-a-LAST-ab-variable/m-p/68091#M14760</guid>
      <dc:creator>Flip</dc:creator>
      <dc:date>2009-08-29T16:55:49Z</dc:date>
    </item>
    <item>
      <title>Re: Combine multiple variables into a LAST.ab variable</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Combine-multiple-variables-into-a-LAST-ab-variable/m-p/68092#M14761</link>
      <description>As is the case with your data example, I made no assumption that there is only one unique B value observation within a give A "set", even after sorting.  He wanted the last occurrence of B for each unique A value. So, there could be more than one observation with a given B value within A -- a condition that would need to be addressed with the IF LAST.B test.&lt;BR /&gt;
&lt;BR /&gt;
Also, there may be usefulness with the additional NOSORTED parameter while using BY and FIRST.&lt;VAR_NAME&gt; and/or LAST.&lt;VAR_NAME&gt;.&lt;BR /&gt;
&lt;BR /&gt;
For some circumstances, I also find consecutive PROC SORT invocations, with the last using EQUALS NODUPKEY -- may or may not apply - just mentioning it for consideration (now or later).&lt;BR /&gt;
&lt;BR /&gt;
&lt;BR /&gt;
Scott Barry&lt;BR /&gt;
SBBWorks, Inc.&lt;/VAR_NAME&gt;&lt;/VAR_NAME&gt;</description>
      <pubDate>Sat, 29 Aug 2009 18:53:28 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Combine-multiple-variables-into-a-LAST-ab-variable/m-p/68092#M14761</guid>
      <dc:creator>sbb</dc:creator>
      <dc:date>2009-08-29T18:53:28Z</dc:date>
    </item>
    <item>
      <title>Re: Combine multiple variables into a LAST.ab variable</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Combine-multiple-variables-into-a-LAST-ab-variable/m-p/68093#M14762</link>
      <description>Again not so;&lt;BR /&gt;
&lt;BR /&gt;
data one;&lt;BR /&gt;
do a = 1 to 2;&lt;BR /&gt;
do b = 1 to 2;&lt;BR /&gt;
do c = 1 to 2;&lt;BR /&gt;
output;&lt;BR /&gt;
end;&lt;BR /&gt;
end;&lt;BR /&gt;
end;&lt;BR /&gt;
run;&lt;BR /&gt;
&lt;BR /&gt;
data two;&lt;BR /&gt;
set one;&lt;BR /&gt;
by a b;&lt;BR /&gt;
&lt;BR /&gt;
la = last.a;&lt;BR /&gt;
lb = last.b;&lt;BR /&gt;
run;&lt;BR /&gt;
proc print;&lt;BR /&gt;
run;&lt;BR /&gt;
&lt;BR /&gt;
&lt;BR /&gt;
Obs    a    b    c    la    lb&lt;BR /&gt;
&lt;BR /&gt;
 1     1    1    1     0     0&lt;BR /&gt;
 2     1    1    2     0     1&lt;BR /&gt;
 3     1    2    1     0     0&lt;BR /&gt;
 4     1    2    2     1     1&lt;BR /&gt;
 5     2    1    1     0     0&lt;BR /&gt;
 6     2    1    2     0     1&lt;BR /&gt;
 7     2    2    1     0     0&lt;BR /&gt;
 8     2    2    2     1     1&lt;BR /&gt;
&lt;BR /&gt;
Note now Obs 3 and 4 have the same value of b.  Again lats.a gives the correct result.  Last.b gives the highest value of c within a given b value.&lt;BR /&gt;
Last.x is the observation of group of x sorted on whatever is next in the by value.   &lt;BR /&gt;
&lt;BR /&gt;
Yes using NODUPKEY solves this, but it is still without question last.A which is correct.</description>
      <pubDate>Sat, 29 Aug 2009 21:37:18 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Combine-multiple-variables-into-a-LAST-ab-variable/m-p/68093#M14762</guid>
      <dc:creator>Flip</dc:creator>
      <dc:date>2009-08-29T21:37:18Z</dc:date>
    </item>
    <item>
      <title>Re: Combine multiple variables into a LAST.ab variable</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Combine-multiple-variables-into-a-LAST-ab-variable/m-p/68094#M14763</link>
      <description>Let's take the DATA step below (using your "modified" WORK.ONE file, having multiple-value B variable instances) -- and given Flip's premise that only filtering on the condition is sufficient:&lt;BR /&gt;
&lt;BR /&gt;
IF LAST.A;&lt;BR /&gt;
&lt;BR /&gt;
which will generate two observations (each unique A value) as compared to the OP request for each unique B within each A condition.&lt;BR /&gt;
&lt;BR /&gt;
Observe the SAS log below with the resulting SAS variables while executing the DATA step with the SET and BY A B; -- the LAST.B condition is clearly "TRUE" more frequently than the LAST.A condition is "TRUE".&lt;BR /&gt;
&lt;BR /&gt;
So, I submit that if the objective is to yield each unique occurrence of both A and B, the code below will generate the combination values in WORK.TWO:&lt;BR /&gt;
&lt;BR /&gt;
DATA TWO;&lt;BR /&gt;
SET ONE;&lt;BR /&gt;
BY A B;&lt;BR /&gt;
IF LAST.B;&lt;BR /&gt;
RUN;&lt;BR /&gt;
&lt;BR /&gt;
From this example data representation, the accurate observation count in WORK.TWO should be 4, whereas having the IF statement:&lt;BR /&gt;
&lt;BR /&gt;
IF LAST.A;&lt;BR /&gt;
&lt;BR /&gt;
will only generate two (2) observations in SAS file WORK.TWO.&lt;BR /&gt;
&lt;BR /&gt;
Scott Barry&lt;BR /&gt;
SBBWorks, Inc.&lt;BR /&gt;
&lt;BR /&gt;
11   data two;&lt;BR /&gt;
12   set one;&lt;BR /&gt;
13   by a b;&lt;BR /&gt;
14   putlog _all_;&lt;BR /&gt;
15   if last.b;&lt;BR /&gt;
16   run;&lt;BR /&gt;
&lt;BR /&gt;
a=1 b=1 c=1 FIRST.a=1 LAST.a=0 FIRST.b=1 LAST.b=0 _ERROR_=0 _N_=1&lt;BR /&gt;
a=1 b=1 c=2 FIRST.a=0 LAST.a=0 FIRST.b=0 LAST.b=1 _ERROR_=0 _N_=2&lt;BR /&gt;
a=1 b=2 c=1 FIRST.a=0 LAST.a=0 FIRST.b=1 LAST.b=0 _ERROR_=0 _N_=3&lt;BR /&gt;
a=1 b=2 c=2 FIRST.a=0 LAST.a=1 FIRST.b=0 LAST.b=1 _ERROR_=0 _N_=4&lt;BR /&gt;
a=2 b=1 c=1 FIRST.a=1 LAST.a=0 FIRST.b=1 LAST.b=0 _ERROR_=0 _N_=5&lt;BR /&gt;
a=2 b=1 c=2 FIRST.a=0 LAST.a=0 FIRST.b=0 LAST.b=1 _ERROR_=0 _N_=6&lt;BR /&gt;
a=2 b=2 c=1 FIRST.a=0 LAST.a=0 FIRST.b=1 LAST.b=0 _ERROR_=0 _N_=7&lt;BR /&gt;
a=2 b=2 c=2 FIRST.a=0 LAST.a=1 FIRST.b=0 LAST.b=1 _ERROR_=0 _N_=8&lt;BR /&gt;
NOTE: There were 8 observations read from the data set WORK.ONE.&lt;BR /&gt;
NOTE: The data set WORK.TWO has 4 observations and 3 variables.&lt;BR /&gt;
NOTE: DATA statement used (Total process time):&lt;BR /&gt;
&lt;SNIP&gt;&lt;/SNIP&gt;</description>
      <pubDate>Sun, 30 Aug 2009 16:35:43 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Combine-multiple-variables-into-a-LAST-ab-variable/m-p/68094#M14763</guid>
      <dc:creator>sbb</dc:creator>
      <dc:date>2009-08-30T16:35:43Z</dc:date>
    </item>
    <item>
      <title>Re: Combine multiple variables into a LAST.ab variable</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Combine-multiple-variables-into-a-LAST-ab-variable/m-p/68095#M14764</link>
      <description>I think that you and I are reading the OP differently.  He states "how do I filter for the last entry of b for each a"  where I am taking this to mean the highest value of B within A, you are reading it as The last value of a given B within A based on some ordering which is not mentioned.&lt;BR /&gt;
&lt;BR /&gt;
The point I am trying to make is demonstrated below.  I purposefully here do not sort on C.  As you see the observation getting last.b is not related to any sort order, and thus can be the 'wrong' observation. &lt;BR /&gt;
&lt;BR /&gt;
As you often state, clarity in a request is of great importance in determining te correct responce.&lt;BR /&gt;
&lt;BR /&gt;
data one;&lt;BR /&gt;
do a = 1 to 2;&lt;BR /&gt;
do b=1 to 2;&lt;BR /&gt;
do c=1 to 2;&lt;BR /&gt;
output;&lt;BR /&gt;
end;&lt;BR /&gt;
end;&lt;BR /&gt;
end;&lt;BR /&gt;
run;&lt;BR /&gt;
&lt;BR /&gt;
proc sort data = one out = two;&lt;BR /&gt;
by a b descending c;&lt;BR /&gt;
run;&lt;BR /&gt;
&lt;BR /&gt;
data one;&lt;BR /&gt;
set one two;&lt;BR /&gt;
run;&lt;BR /&gt;
&lt;BR /&gt;
proc sort data = one out = two;&lt;BR /&gt;
by a b ;&lt;BR /&gt;
run;&lt;BR /&gt;
&lt;BR /&gt;
data one;&lt;BR /&gt;
set two;&lt;BR /&gt;
by a b;&lt;BR /&gt;
la = last.a;&lt;BR /&gt;
lb = last.b;&lt;BR /&gt;
run;&lt;BR /&gt;
&lt;BR /&gt;
proc print;&lt;BR /&gt;
run;&lt;BR /&gt;
The SAS System                                                                                 16:00 Sunday, August 30, 2009   1&lt;BR /&gt;
&lt;BR /&gt;
Obs    a    b    c    la    lb&lt;BR /&gt;
&lt;BR /&gt;
  1    1    1    1     0     0&lt;BR /&gt;
  2    1    1    2     0     0&lt;BR /&gt;
  3    1    1    2     0     0&lt;BR /&gt;
  4    1    1    1     0     1&lt;BR /&gt;
  5    1    2    1     0     0&lt;BR /&gt;
  6    1    2    2     0     0&lt;BR /&gt;
  7    1    2    2     0     0&lt;BR /&gt;
  8    1    2    1     1     1&lt;BR /&gt;
  9    2    1    1     0     0&lt;BR /&gt;
 10    2    1    2     0     0&lt;BR /&gt;
 11    2    1    2     0     0&lt;BR /&gt;
 12    2    1    1     0     1&lt;BR /&gt;
 13    2    2    1     0     0&lt;BR /&gt;
 14    2    2    2     0     0&lt;BR /&gt;
 15    2    2    2     0     0&lt;BR /&gt;
 16    2    2    1     1     1</description>
      <pubDate>Sun, 30 Aug 2009 20:12:01 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Combine-multiple-variables-into-a-LAST-ab-variable/m-p/68095#M14764</guid>
      <dc:creator>Flip</dc:creator>
      <dc:date>2009-08-30T20:12:01Z</dc:date>
    </item>
    <item>
      <title>Re: Combine multiple variables into a LAST.ab variable</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Combine-multiple-variables-into-a-LAST-ab-variable/m-p/68096#M14765</link>
      <description>Humbly, let's observe the initial thread question.  Here's the first sentence from the OP:&lt;BR /&gt;
&lt;BR /&gt;
"If I have a dataset with variables a and b and I sort by a then b how do I filter for the last entry of b for each a. "&lt;BR /&gt;
&lt;BR /&gt;
Of course, I presume that he wants the "last entry" of each B variable value captured for output (which would be the default, since he didn't mention DESCENDING B as a sort criteria specification), with each A variable value (also a contributing "break" variable by definition).  The SAS variable B is mentioned as a contributing data-variable to the sort order.&lt;BR /&gt;
&lt;BR /&gt;
Again, with your second data-set as a decent sample to demonstrate the importance of testing IF LAST.B; , you will either get:&lt;BR /&gt;
&lt;BR /&gt;
- four output observations:  one obs for each unique A variable value and unique B variable value.&lt;BR /&gt;
&lt;BR /&gt;
- two observations: one for each unique A variable value - oh, by the way, the value of B will be whatever occurred on the last/highest observation of A.&lt;BR /&gt;
&lt;BR /&gt;
Clearly, data dependent, but the lack of testing:  IF LAST.B;   could yield incomplete output data.&lt;BR /&gt;
&lt;BR /&gt;
If you believe that there should only be 2 observations - but the important point here is the need to have a "break" test (for output/filter) selection that includes variable B as well as variable A.  That is where we have a difference of technical opinion, I believe.&lt;BR /&gt;
&lt;BR /&gt;
&lt;BR /&gt;
Scott Barry&lt;BR /&gt;
SBBWorks, Inc.</description>
      <pubDate>Sun, 30 Aug 2009 20:59:28 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Combine-multiple-variables-into-a-LAST-ab-variable/m-p/68096#M14765</guid>
      <dc:creator>sbb</dc:creator>
      <dc:date>2009-08-30T20:59:28Z</dc:date>
    </item>
    <item>
      <title>Re: Combine multiple variables into a LAST.ab variable</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Combine-multiple-variables-into-a-LAST-ab-variable/m-p/68097#M14766</link>
      <description>Oh, just for the fun of discussion, a couple of points.&lt;BR /&gt;
&lt;BR /&gt;
SBB: "- two observations: one for each unique A variable value - oh, by the way, the value of B will be whatever occurred on the last/highest observation of A."&lt;BR /&gt;
&lt;BR /&gt;
Actually the value of B would be the maximum value of B within a given A.  Last.A order is driven by the sort order of B within A.  It will return any old value of C, which is my point.&lt;BR /&gt;
&lt;BR /&gt;
OP: "If I have a dataset with variables a and b and I sort by a then b"&lt;BR /&gt;
&lt;BR /&gt;
with only A and B in the data set.  sorted by A and B  with multiple equivalent values of B within a given A, the statements first.B, last.B, anyold.B would give identical records from A-B pairs.&lt;BR /&gt;
&lt;BR /&gt;
The reason I stress this is that I have seen several programmers write code like this when trying to get the record with the maximum value of B within A and got the result you are talking about instead.  And yes, I can see that the way you are reading the OP could be what he intended, I did not read it that way.&lt;BR /&gt;
&lt;BR /&gt;
Thanks for the discussion.</description>
      <pubDate>Mon, 31 Aug 2009 13:35:12 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Combine-multiple-variables-into-a-LAST-ab-variable/m-p/68097#M14766</guid>
      <dc:creator>Flip</dc:creator>
      <dc:date>2009-08-31T13:35:12Z</dc:date>
    </item>
  </channel>
</rss>

