<?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: Clear the LAG queue in SAS Programming</title>
    <link>https://communities.sas.com/t5/SAS-Programming/Clear-the-LAG-queue/m-p/485297#M126061</link>
    <description>&lt;P&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/225366"&gt;@craigsrsen&lt;/a&gt;:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;It cannot be done &lt;EM&gt;after&lt;/EM&gt; the BY group, and here's why. Suppose you have data as below and attempt to clean the queues after each BY group by repeatedly dequeueing in a loop up to the length of the longest lag:&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data test ;            
  input id v ;         
  cards ;              
2 1                    
2 2                    
3 1                    
3 2                    
3 3                    
;                      
run ;                  
                       
data _null_ ;          
  do until (last.id) ; 
    set test ;         
    by id ;            
    x1 = lag1 (v) ;    
    x2 = lag2 (v) ;    
    put _n_= x1= x2= ; 
  end ;                
  do _n_ = 1 to 2 ;    
    x = lag1 (.) ;     
    x = lag2 (.) ;     
  end ;                
run ;                  &lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;What you'll see in the log will be (note that _N_ below is the BY group number):&amp;nbsp;&lt;/P&gt;&lt;PRE&gt;_N_=1 x1=. x2=.
_N_=1 x1=1 x2=.
_N_=2 x1=2 x2=1
_N_=2 x1=1 x2=2
_N_=2 x1=2 x2=1&lt;/PRE&gt;&lt;P&gt;&amp;nbsp;Obviously, nothing has been cleaned up. The reason is that when the compiler sees LAG1 and LAG2 for the second time, it allocates totally new queues having nothing whatsoever to do with the queues referenced in the BY group DO loop, and so the "clean-up" DO loop executes against the second set of the LAGs. The only two ways I see to work around it are:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;1. Organize your queues using arrays or hash tables (it's actually pretty easy).&lt;/P&gt;&lt;P&gt;2. To the end of each BY group, add as many dummy records as the length of the longest lag. This way, the compiler will see the lags only once but the dummy records will dequeue them before the next BY group appears.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;WRT #2, for example:&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;%let maxlag = 2 ; * longest lag ;        
                                         
data dummy / view = dummy ;              
  set test ;                             
  by id ;                                
  output ;                               
  v = . ;                                
  if last.id then do _n_ = 1 to &amp;amp;maxlag ;
    output ;                             
  end ;                                  
run ;                                    
                                         
data _null_ ;                            
  do until (last.id) ;                   
    set dummy ;                          
    by id ;                              
    x1 = lag1 (v) ;                      
    x2 = lag2 (v) ;                      
    put _n_= x1= x2= ;                   
  end ;                                  
run ;                                    &lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;In this case, you'll see in the log:&lt;/P&gt;&lt;PRE&gt;_N_=1 x1=. x2=.
_N_=1 x1=1 x2=.
_N_=1 x1=2 x2=1
_N_=1 x1=. x2=2
_N_=2 x1=. x2=.
_N_=2 x1=1 x2=.
_N_=2 x1=2 x2=1
_N_=2 x1=3 x2=2
_N_=2 x1=. x2=3&lt;/PRE&gt;&lt;P&gt;as you'd expect since the lags have been dequeued by calling them for each dummy record. In your program, you'll have to include some conditional statement to separate your processing of the real records from the dummy ones - just make sure it doesn't include any reference to LAG1 or LAG2 ;).&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Paul D.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
    <pubDate>Wed, 08 Aug 2018 22:01:48 GMT</pubDate>
    <dc:creator>hashman</dc:creator>
    <dc:date>2018-08-08T22:01:48Z</dc:date>
    <item>
      <title>Clear the LAG queue</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Clear-the-LAG-queue/m-p/485285#M126057</link>
      <description>&lt;P&gt;I have a dataset that I am processing in BY-groups and am using multiple LAG functions, e.g. a LAG1 variable, a LAG2 variable, etc.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;When I reach a new BY group, I want to clear the entire LAG queue from memory and start over. If I use FIRST. I can clear lagged values from the first record in a BY group, but on the second record of the BY group I am still pulling in lagged values from the previous BY group.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I could probably devise a work-around but I am wondering if there is a simple command to clear the entire LAG queue.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Thanks&lt;/P&gt;</description>
      <pubDate>Wed, 08 Aug 2018 20:38:50 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Clear-the-LAG-queue/m-p/485285#M126057</guid>
      <dc:creator>craigsrsen</dc:creator>
      <dc:date>2018-08-08T20:38:50Z</dc:date>
    </item>
    <item>
      <title>Re: Clear the LAG queue</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Clear-the-LAG-queue/m-p/485294#M126060</link>
      <description>&lt;BLOCKQUOTE&gt;&lt;HR /&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/225366"&gt;@craigsrsen&lt;/a&gt;&amp;nbsp;wrote:&lt;BR /&gt;
&lt;P&gt;I have a dataset that I am processing in BY-groups and am using multiple LAG functions, e.g. a LAG1 variable, a LAG2 variable, etc.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;When I reach a new BY group, I want to clear the entire LAG queue from memory and start over. If I use FIRST. I can clear lagged values from the first record in a BY group, but on the second record of the BY group I am still pulling in lagged values from the previous BY group.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I could probably devise a work-around but I am wondering if there is a simple command to clear the entire LAG queue.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Thanks&lt;/P&gt;
&lt;HR /&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;No simple way to clear the lag queue entirely.&lt;/P&gt;
&lt;P&gt;If you show the code you are currently attempting we can make suggestions that may work in this case.&lt;/P&gt;
&lt;P&gt;Likely it is going to involve a counter within the by group and conditional assignment to a different variable than a simple lagn()&lt;/P&gt;</description>
      <pubDate>Wed, 08 Aug 2018 21:38:51 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Clear-the-LAG-queue/m-p/485294#M126060</guid>
      <dc:creator>ballardw</dc:creator>
      <dc:date>2018-08-08T21:38:51Z</dc:date>
    </item>
    <item>
      <title>Re: Clear the LAG queue</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Clear-the-LAG-queue/m-p/485297#M126061</link>
      <description>&lt;P&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/225366"&gt;@craigsrsen&lt;/a&gt;:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;It cannot be done &lt;EM&gt;after&lt;/EM&gt; the BY group, and here's why. Suppose you have data as below and attempt to clean the queues after each BY group by repeatedly dequeueing in a loop up to the length of the longest lag:&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data test ;            
  input id v ;         
  cards ;              
2 1                    
2 2                    
3 1                    
3 2                    
3 3                    
;                      
run ;                  
                       
data _null_ ;          
  do until (last.id) ; 
    set test ;         
    by id ;            
    x1 = lag1 (v) ;    
    x2 = lag2 (v) ;    
    put _n_= x1= x2= ; 
  end ;                
  do _n_ = 1 to 2 ;    
    x = lag1 (.) ;     
    x = lag2 (.) ;     
  end ;                
run ;                  &lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;What you'll see in the log will be (note that _N_ below is the BY group number):&amp;nbsp;&lt;/P&gt;&lt;PRE&gt;_N_=1 x1=. x2=.
_N_=1 x1=1 x2=.
_N_=2 x1=2 x2=1
_N_=2 x1=1 x2=2
_N_=2 x1=2 x2=1&lt;/PRE&gt;&lt;P&gt;&amp;nbsp;Obviously, nothing has been cleaned up. The reason is that when the compiler sees LAG1 and LAG2 for the second time, it allocates totally new queues having nothing whatsoever to do with the queues referenced in the BY group DO loop, and so the "clean-up" DO loop executes against the second set of the LAGs. The only two ways I see to work around it are:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;1. Organize your queues using arrays or hash tables (it's actually pretty easy).&lt;/P&gt;&lt;P&gt;2. To the end of each BY group, add as many dummy records as the length of the longest lag. This way, the compiler will see the lags only once but the dummy records will dequeue them before the next BY group appears.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;WRT #2, for example:&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;%let maxlag = 2 ; * longest lag ;        
                                         
data dummy / view = dummy ;              
  set test ;                             
  by id ;                                
  output ;                               
  v = . ;                                
  if last.id then do _n_ = 1 to &amp;amp;maxlag ;
    output ;                             
  end ;                                  
run ;                                    
                                         
data _null_ ;                            
  do until (last.id) ;                   
    set dummy ;                          
    by id ;                              
    x1 = lag1 (v) ;                      
    x2 = lag2 (v) ;                      
    put _n_= x1= x2= ;                   
  end ;                                  
run ;                                    &lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;In this case, you'll see in the log:&lt;/P&gt;&lt;PRE&gt;_N_=1 x1=. x2=.
_N_=1 x1=1 x2=.
_N_=1 x1=2 x2=1
_N_=1 x1=. x2=2
_N_=2 x1=. x2=.
_N_=2 x1=1 x2=.
_N_=2 x1=2 x2=1
_N_=2 x1=3 x2=2
_N_=2 x1=. x2=3&lt;/PRE&gt;&lt;P&gt;as you'd expect since the lags have been dequeued by calling them for each dummy record. In your program, you'll have to include some conditional statement to separate your processing of the real records from the dummy ones - just make sure it doesn't include any reference to LAG1 or LAG2 ;).&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Paul D.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Wed, 08 Aug 2018 22:01:48 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Clear-the-LAG-queue/m-p/485297#M126061</guid>
      <dc:creator>hashman</dc:creator>
      <dc:date>2018-08-08T22:01:48Z</dc:date>
    </item>
    <item>
      <title>Re: Clear the LAG queue</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Clear-the-LAG-queue/m-p/485315#M126068</link>
      <description>&lt;P&gt;This is probably how I would implement a proper-queue logic:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;proc sort data=SASHELP.CLASS out=CLASS; 
  by SEX NAME;
run;
data CLASS2;
 set CLASS;
  by SEX;
  N1=lag1(NAME) ;
  N2=lag2(NAME) ;
  if SEX ne lag1(SEX) then N1=' ';
  if SEX ne lag2(SEX) then N2=' ';
run;
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;It's easy to read and to debug.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Thu, 09 Aug 2018 00:11:23 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Clear-the-LAG-queue/m-p/485315#M126068</guid>
      <dc:creator>ChrisNZ</dc:creator>
      <dc:date>2018-08-09T00:11:23Z</dc:date>
    </item>
    <item>
      <title>Re: Clear the LAG queue</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Clear-the-LAG-queue/m-p/485320#M126069</link>
      <description>&lt;P&gt;You can just use RETAIN instead of LAG().&amp;nbsp; Then it is easy to just use CALL MISSING();&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data want ;
   lag5=lag4;
   lag4=lag3;
   lag3=lag2;
   lag2=lag1;
   lag1=x;
   retain lag1-lag5 ;
   set have ;
   by id;
   if first.id then call missing(of lag1-lag5);

   .... do stuff  ...

run;
  &lt;/CODE&gt;&lt;/PRE&gt;</description>
      <pubDate>Thu, 09 Aug 2018 00:37:03 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Clear-the-LAG-queue/m-p/485320#M126069</guid>
      <dc:creator>Tom</dc:creator>
      <dc:date>2018-08-09T00:37:03Z</dc:date>
    </item>
    <item>
      <title>Re: Clear the LAG queue</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Clear-the-LAG-queue/m-p/485339#M126081</link>
      <description>&lt;P&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/159"&gt;@Tom&lt;/a&gt;:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Exactly. You're essentially organizing a queue as an expanded (unrolled) array. As such, it can be coded as an unexpanded array as well; and:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;- if it is non-temporary, CALL MISSING is not needed&lt;/P&gt;&lt;P&gt;- and if the DoW loop is used, RETAIN isn't needed, either&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;E.g.:&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data have ;                                               
  do ID = "A", "B" ;                                      
    do x = 1 to 9 ;                                       
      output ;                                            
    end ;                                                 
  end ;                                                   
run ;                                                     
                                                          
data want (drop = _:) ;                                   
  do until (last.id) ;                                    
    set have ;                                            
    by ID ;                                               
    array xq [*] x _q1-_q5 ;                       
    do _i = dim (xq) to 2 by -1 ;                      
      xq [_i] = xq [_i - 1] ;                       
    end ;                                                 
    put ID= x= " q: " _q1-_q5 ;
    /* do stuff */                                        
  end ;                                                   
run ;                                                     &lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;And the log will show:&lt;/P&gt;&lt;PRE&gt;ID=A x=1 q: 1 . . . .&lt;BR /&gt;ID=A x=2 q: 2 1 . . .&lt;BR /&gt;ID=A x=3 q: 3 2 1 . .&lt;BR /&gt;ID=A x=4 q: 4 3 2 1 .&lt;BR /&gt;ID=A x=5 q: 5 4 3 2 1&lt;BR /&gt;ID=A x=6 q: 6 5 4 3 2&lt;BR /&gt;ID=A x=7 q: 7 6 5 4 3&lt;BR /&gt;ID=A x=8 q: 8 7 6 5 4&lt;BR /&gt;ID=A x=9 q: 9 8 7 6 5&lt;BR /&gt;ID=B x=1 q: 1 . . . .&lt;BR /&gt;ID=B x=2 q: 2 1 . . .&lt;BR /&gt;ID=B x=3 q: 3 2 1 . .&lt;BR /&gt;ID=B x=4 q: 4 3 2 1 .&lt;BR /&gt;ID=B x=5 q: 5 4 3 2 1&lt;BR /&gt;ID=B x=6 q: 6 5 4 3 2&lt;BR /&gt;ID=B x=7 q: 7 6 5 4 3&lt;BR /&gt;ID=B x=8 q: 8 7 6 5 4&lt;BR /&gt;ID=B x=9 q: 9 8 7 6 5&lt;/PRE&gt;&lt;P&gt;Quod erat faciendum.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;One little issue with this way of organizing a queue is the need to shift all the q-values one position backward for each record read from the file. However, that can be easily recoded by either (a) allocating a "big enough" array and merely adjusting index pointers instead of moving the values or (b) using a hash table with its advantage of dynamic sizing. (In fact, there's a section on organizing a hash queue in Chapter 10 of the book "Data Management Solutions Using SAS Hash Table Operations" just published by SAS Press and penned by Don Henderson and yours truly.)&amp;nbsp; &amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Best&lt;/P&gt;&lt;P&gt;Paul D.&lt;/P&gt;</description>
      <pubDate>Thu, 09 Aug 2018 03:26:43 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Clear-the-LAG-queue/m-p/485339#M126081</guid>
      <dc:creator>hashman</dc:creator>
      <dc:date>2018-08-09T03:26:43Z</dc:date>
    </item>
    <item>
      <title>Re: Clear the LAG queue</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Clear-the-LAG-queue/m-p/485956#M126332</link>
      <description>&lt;P&gt;Thanks Chris. This is basically the solution I ended up going with. It was pretty straightforward.&lt;/P&gt;</description>
      <pubDate>Fri, 10 Aug 2018 21:04:27 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Clear-the-LAG-queue/m-p/485956#M126332</guid>
      <dc:creator>craigsrsen</dc:creator>
      <dc:date>2018-08-10T21:04:27Z</dc:date>
    </item>
  </channel>
</rss>

