Dynamic n in function LAG (variable) SAS_part2












0















do you know how to use n in function LAGn(variable) that refer to another macro variable in the program-> max in my case by V1?



   data example1;
input V1 value V2;
datalines;
a 1.0 2.0
a 1.0 1.0
a 1.0 1.0
b 1.0 1.0
b 1.0 1.0
;

proc sql;
select max(V2) format = 1. into :n
from example1;
quit;

data example1;
set example1;
by V1;
lagval=lag&n(V2);
run;


Code from user667489 and works for one column. Now n changes by V1.
I expect:



          MAX LAG
a 1.0 2.0 2 .
a 1.0 1.0 2 .
a 1.0 1.0 2 2
b 1.0 1.0 1 .
b 1.0 1.0 1 1
;









share|improve this question

























  • Why are taking the maximum of the two variables in ONLY the FIRST observation of EXAMPLE1 and placing it into the macro variable N? What are you actually trying to find the maximum of? How do you know it is an integer? Why do you want to use that as the N in the LAGn() function calls? This is beginning to look like an X-Y problem. What is the real problem you are trying to solve? Perhaps there is another solution that does not need LAG() or macro variables.

    – Tom
    Nov 28 '18 at 14:07













  • Show what result to you want for your given input data will perhaps help to clarify what you are trying to do. For code generation problems like this it is also important to show the code you want to generate.

    – Tom
    Nov 28 '18 at 14:12











  • What do you "now n changes"? Is n going to change during the data-step? One thing to keep in mind is that lag1(x) just returns the value of x had the last time lag(x) was called. Similarly, lag2(x) just returns the value x had when lag(x) was called two times ago.

    – Josh Eller
    Nov 28 '18 at 14:19











  • I added more information. I need function LAG per group.

    – Wioleta Zgliczyńska
    Nov 28 '18 at 14:49











  • Are you saying for group with V1='a' you want LAG2(value) and for group with V1='b' you want LAG1(value)? Again show your expected results.

    – Tom
    Nov 28 '18 at 15:07


















0















do you know how to use n in function LAGn(variable) that refer to another macro variable in the program-> max in my case by V1?



   data example1;
input V1 value V2;
datalines;
a 1.0 2.0
a 1.0 1.0
a 1.0 1.0
b 1.0 1.0
b 1.0 1.0
;

proc sql;
select max(V2) format = 1. into :n
from example1;
quit;

data example1;
set example1;
by V1;
lagval=lag&n(V2);
run;


Code from user667489 and works for one column. Now n changes by V1.
I expect:



          MAX LAG
a 1.0 2.0 2 .
a 1.0 1.0 2 .
a 1.0 1.0 2 2
b 1.0 1.0 1 .
b 1.0 1.0 1 1
;









share|improve this question

























  • Why are taking the maximum of the two variables in ONLY the FIRST observation of EXAMPLE1 and placing it into the macro variable N? What are you actually trying to find the maximum of? How do you know it is an integer? Why do you want to use that as the N in the LAGn() function calls? This is beginning to look like an X-Y problem. What is the real problem you are trying to solve? Perhaps there is another solution that does not need LAG() or macro variables.

    – Tom
    Nov 28 '18 at 14:07













  • Show what result to you want for your given input data will perhaps help to clarify what you are trying to do. For code generation problems like this it is also important to show the code you want to generate.

    – Tom
    Nov 28 '18 at 14:12











  • What do you "now n changes"? Is n going to change during the data-step? One thing to keep in mind is that lag1(x) just returns the value of x had the last time lag(x) was called. Similarly, lag2(x) just returns the value x had when lag(x) was called two times ago.

    – Josh Eller
    Nov 28 '18 at 14:19











  • I added more information. I need function LAG per group.

    – Wioleta Zgliczyńska
    Nov 28 '18 at 14:49











  • Are you saying for group with V1='a' you want LAG2(value) and for group with V1='b' you want LAG1(value)? Again show your expected results.

    – Tom
    Nov 28 '18 at 15:07
















0












0








0


1






do you know how to use n in function LAGn(variable) that refer to another macro variable in the program-> max in my case by V1?



   data example1;
input V1 value V2;
datalines;
a 1.0 2.0
a 1.0 1.0
a 1.0 1.0
b 1.0 1.0
b 1.0 1.0
;

proc sql;
select max(V2) format = 1. into :n
from example1;
quit;

data example1;
set example1;
by V1;
lagval=lag&n(V2);
run;


Code from user667489 and works for one column. Now n changes by V1.
I expect:



          MAX LAG
a 1.0 2.0 2 .
a 1.0 1.0 2 .
a 1.0 1.0 2 2
b 1.0 1.0 1 .
b 1.0 1.0 1 1
;









share|improve this question
















do you know how to use n in function LAGn(variable) that refer to another macro variable in the program-> max in my case by V1?



   data example1;
input V1 value V2;
datalines;
a 1.0 2.0
a 1.0 1.0
a 1.0 1.0
b 1.0 1.0
b 1.0 1.0
;

proc sql;
select max(V2) format = 1. into :n
from example1;
quit;

data example1;
set example1;
by V1;
lagval=lag&n(V2);
run;


Code from user667489 and works for one column. Now n changes by V1.
I expect:



          MAX LAG
a 1.0 2.0 2 .
a 1.0 1.0 2 .
a 1.0 1.0 2 2
b 1.0 1.0 1 .
b 1.0 1.0 1 1
;






sas sas-macro






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 28 '18 at 15:28







Wioleta Zgliczyńska

















asked Nov 28 '18 at 14:01









Wioleta ZgliczyńskaWioleta Zgliczyńska

325




325













  • Why are taking the maximum of the two variables in ONLY the FIRST observation of EXAMPLE1 and placing it into the macro variable N? What are you actually trying to find the maximum of? How do you know it is an integer? Why do you want to use that as the N in the LAGn() function calls? This is beginning to look like an X-Y problem. What is the real problem you are trying to solve? Perhaps there is another solution that does not need LAG() or macro variables.

    – Tom
    Nov 28 '18 at 14:07













  • Show what result to you want for your given input data will perhaps help to clarify what you are trying to do. For code generation problems like this it is also important to show the code you want to generate.

    – Tom
    Nov 28 '18 at 14:12











  • What do you "now n changes"? Is n going to change during the data-step? One thing to keep in mind is that lag1(x) just returns the value of x had the last time lag(x) was called. Similarly, lag2(x) just returns the value x had when lag(x) was called two times ago.

    – Josh Eller
    Nov 28 '18 at 14:19











  • I added more information. I need function LAG per group.

    – Wioleta Zgliczyńska
    Nov 28 '18 at 14:49











  • Are you saying for group with V1='a' you want LAG2(value) and for group with V1='b' you want LAG1(value)? Again show your expected results.

    – Tom
    Nov 28 '18 at 15:07





















  • Why are taking the maximum of the two variables in ONLY the FIRST observation of EXAMPLE1 and placing it into the macro variable N? What are you actually trying to find the maximum of? How do you know it is an integer? Why do you want to use that as the N in the LAGn() function calls? This is beginning to look like an X-Y problem. What is the real problem you are trying to solve? Perhaps there is another solution that does not need LAG() or macro variables.

    – Tom
    Nov 28 '18 at 14:07













  • Show what result to you want for your given input data will perhaps help to clarify what you are trying to do. For code generation problems like this it is also important to show the code you want to generate.

    – Tom
    Nov 28 '18 at 14:12











  • What do you "now n changes"? Is n going to change during the data-step? One thing to keep in mind is that lag1(x) just returns the value of x had the last time lag(x) was called. Similarly, lag2(x) just returns the value x had when lag(x) was called two times ago.

    – Josh Eller
    Nov 28 '18 at 14:19











  • I added more information. I need function LAG per group.

    – Wioleta Zgliczyńska
    Nov 28 '18 at 14:49











  • Are you saying for group with V1='a' you want LAG2(value) and for group with V1='b' you want LAG1(value)? Again show your expected results.

    – Tom
    Nov 28 '18 at 15:07



















Why are taking the maximum of the two variables in ONLY the FIRST observation of EXAMPLE1 and placing it into the macro variable N? What are you actually trying to find the maximum of? How do you know it is an integer? Why do you want to use that as the N in the LAGn() function calls? This is beginning to look like an X-Y problem. What is the real problem you are trying to solve? Perhaps there is another solution that does not need LAG() or macro variables.

– Tom
Nov 28 '18 at 14:07







Why are taking the maximum of the two variables in ONLY the FIRST observation of EXAMPLE1 and placing it into the macro variable N? What are you actually trying to find the maximum of? How do you know it is an integer? Why do you want to use that as the N in the LAGn() function calls? This is beginning to look like an X-Y problem. What is the real problem you are trying to solve? Perhaps there is another solution that does not need LAG() or macro variables.

– Tom
Nov 28 '18 at 14:07















Show what result to you want for your given input data will perhaps help to clarify what you are trying to do. For code generation problems like this it is also important to show the code you want to generate.

– Tom
Nov 28 '18 at 14:12





Show what result to you want for your given input data will perhaps help to clarify what you are trying to do. For code generation problems like this it is also important to show the code you want to generate.

– Tom
Nov 28 '18 at 14:12













What do you "now n changes"? Is n going to change during the data-step? One thing to keep in mind is that lag1(x) just returns the value of x had the last time lag(x) was called. Similarly, lag2(x) just returns the value x had when lag(x) was called two times ago.

– Josh Eller
Nov 28 '18 at 14:19





What do you "now n changes"? Is n going to change during the data-step? One thing to keep in mind is that lag1(x) just returns the value of x had the last time lag(x) was called. Similarly, lag2(x) just returns the value x had when lag(x) was called two times ago.

– Josh Eller
Nov 28 '18 at 14:19













I added more information. I need function LAG per group.

– Wioleta Zgliczyńska
Nov 28 '18 at 14:49





I added more information. I need function LAG per group.

– Wioleta Zgliczyńska
Nov 28 '18 at 14:49













Are you saying for group with V1='a' you want LAG2(value) and for group with V1='b' you want LAG1(value)? Again show your expected results.

– Tom
Nov 28 '18 at 15:07







Are you saying for group with V1='a' you want LAG2(value) and for group with V1='b' you want LAG1(value)? Again show your expected results.

– Tom
Nov 28 '18 at 15:07














2 Answers
2






active

oldest

votes


















1














Forget about LAG(). Just add a counter variable and join on that.



Let's fix your example data step so it works.



data example1;
input V1 $ value V2;
datalines;
a 1 2
a 1 1
a 1 1
b 1 1
b 1 1
;


Now add a unique row id within each BY group.



data step1;
set example1;
by v1;
if first.v1 then row=0;
row+1;
run;


Now just join this dataset with itself.



proc sql ;
create table want as
select a.*,b.v2 as lag_v2
from (select *,max(v2) as max_v2 from step1 group by v1) a
left join step1 b
on a.v1= b.v1 and a.row = b.row + a.max_v2
;
quit;


Results:



Obs    V1    value    V2    row    max_v2    lag_v2

1 a 1 2 1 2 .
2 a 1 1 2 2 .
3 a 1 1 3 2 2
4 b 1 1 1 1 .
5 b 1 1 2 1 1


Hopefully your real use case makes more sense than than this example.






share|improve this answer

































    0














    The LAG<n> function is an in-place stack of fixed depth that is specific to it's code use location and thus step state at invocation. The stack is of depth and can not be altered dynamically at runtime.



    A dynamic lag can be implemented in SAS DATA step using a hash object. The double DOW technique allows a group to be measured and then subsequently it's items operated upon.



    Sample code



    This example uses a defines a hash object that maintains a stack of values within a group. A first DOW loop computes the maximum of a field that becomes the dynamic stack height. The second DOW loop iterates of the group and retrieves the lag value while also building up the stack for future item lags.



    * some faux data;

    data have (keep=group value duration);
    do group = 1 to 10;
    limit = ceil(4 * ranuni(6));
    put group= limit=;
    do _n_ = 1 to 8 + 10*ranuni(123);
    value = group*10 + _n_;
    duration = 1 + floor(limit*ranuni(123));
    output;
    end;
    end;
    run;

    * dynamic lag provided via hash;

    data want;
    if _n_ = 1 then do;
    retain index lag_value .;
    declare hash lag_stack();
    lag_stack.defineKey('index');
    lag_stack.defineData('lag_value');
    lag_stack.defineDone();
    end;

    do _n_ = 1 by 1 until (last.group);
    set have;
    by group;
    max_duration = max(max_duration, duration);
    end;

    * max_duration within group is the lag lag_stack height;

    * pre-fill missings ;
    do index = 1-max_duration to 0;
    lag_stack.replace(key: index, data: .);
    end;

    do _n_ = 1 to _n_;
    set have;
    lag_stack.replace(key: _n_, data: value);
    lag_stack.find(key: _n_ - max_duration);
    output;
    end;

    drop index;
    run;


    Another technique would involve a fixed length ring-array instead of a hash-stack, but you would need to compute the maximum lag over all groups prior to coding the DATA step using the array.






    share|improve this answer























      Your Answer






      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "1"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53521202%2fdynamic-n-in-function-lagn-variable-sas-part2%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      2 Answers
      2






      active

      oldest

      votes








      2 Answers
      2






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      1














      Forget about LAG(). Just add a counter variable and join on that.



      Let's fix your example data step so it works.



      data example1;
      input V1 $ value V2;
      datalines;
      a 1 2
      a 1 1
      a 1 1
      b 1 1
      b 1 1
      ;


      Now add a unique row id within each BY group.



      data step1;
      set example1;
      by v1;
      if first.v1 then row=0;
      row+1;
      run;


      Now just join this dataset with itself.



      proc sql ;
      create table want as
      select a.*,b.v2 as lag_v2
      from (select *,max(v2) as max_v2 from step1 group by v1) a
      left join step1 b
      on a.v1= b.v1 and a.row = b.row + a.max_v2
      ;
      quit;


      Results:



      Obs    V1    value    V2    row    max_v2    lag_v2

      1 a 1 2 1 2 .
      2 a 1 1 2 2 .
      3 a 1 1 3 2 2
      4 b 1 1 1 1 .
      5 b 1 1 2 1 1


      Hopefully your real use case makes more sense than than this example.






      share|improve this answer






























        1














        Forget about LAG(). Just add a counter variable and join on that.



        Let's fix your example data step so it works.



        data example1;
        input V1 $ value V2;
        datalines;
        a 1 2
        a 1 1
        a 1 1
        b 1 1
        b 1 1
        ;


        Now add a unique row id within each BY group.



        data step1;
        set example1;
        by v1;
        if first.v1 then row=0;
        row+1;
        run;


        Now just join this dataset with itself.



        proc sql ;
        create table want as
        select a.*,b.v2 as lag_v2
        from (select *,max(v2) as max_v2 from step1 group by v1) a
        left join step1 b
        on a.v1= b.v1 and a.row = b.row + a.max_v2
        ;
        quit;


        Results:



        Obs    V1    value    V2    row    max_v2    lag_v2

        1 a 1 2 1 2 .
        2 a 1 1 2 2 .
        3 a 1 1 3 2 2
        4 b 1 1 1 1 .
        5 b 1 1 2 1 1


        Hopefully your real use case makes more sense than than this example.






        share|improve this answer




























          1












          1








          1







          Forget about LAG(). Just add a counter variable and join on that.



          Let's fix your example data step so it works.



          data example1;
          input V1 $ value V2;
          datalines;
          a 1 2
          a 1 1
          a 1 1
          b 1 1
          b 1 1
          ;


          Now add a unique row id within each BY group.



          data step1;
          set example1;
          by v1;
          if first.v1 then row=0;
          row+1;
          run;


          Now just join this dataset with itself.



          proc sql ;
          create table want as
          select a.*,b.v2 as lag_v2
          from (select *,max(v2) as max_v2 from step1 group by v1) a
          left join step1 b
          on a.v1= b.v1 and a.row = b.row + a.max_v2
          ;
          quit;


          Results:



          Obs    V1    value    V2    row    max_v2    lag_v2

          1 a 1 2 1 2 .
          2 a 1 1 2 2 .
          3 a 1 1 3 2 2
          4 b 1 1 1 1 .
          5 b 1 1 2 1 1


          Hopefully your real use case makes more sense than than this example.






          share|improve this answer















          Forget about LAG(). Just add a counter variable and join on that.



          Let's fix your example data step so it works.



          data example1;
          input V1 $ value V2;
          datalines;
          a 1 2
          a 1 1
          a 1 1
          b 1 1
          b 1 1
          ;


          Now add a unique row id within each BY group.



          data step1;
          set example1;
          by v1;
          if first.v1 then row=0;
          row+1;
          run;


          Now just join this dataset with itself.



          proc sql ;
          create table want as
          select a.*,b.v2 as lag_v2
          from (select *,max(v2) as max_v2 from step1 group by v1) a
          left join step1 b
          on a.v1= b.v1 and a.row = b.row + a.max_v2
          ;
          quit;


          Results:



          Obs    V1    value    V2    row    max_v2    lag_v2

          1 a 1 2 1 2 .
          2 a 1 1 2 2 .
          3 a 1 1 3 2 2
          4 b 1 1 1 1 .
          5 b 1 1 2 1 1


          Hopefully your real use case makes more sense than than this example.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 29 '18 at 16:45

























          answered Nov 29 '18 at 16:31









          TomTom

          24.4k2720




          24.4k2720

























              0














              The LAG<n> function is an in-place stack of fixed depth that is specific to it's code use location and thus step state at invocation. The stack is of depth and can not be altered dynamically at runtime.



              A dynamic lag can be implemented in SAS DATA step using a hash object. The double DOW technique allows a group to be measured and then subsequently it's items operated upon.



              Sample code



              This example uses a defines a hash object that maintains a stack of values within a group. A first DOW loop computes the maximum of a field that becomes the dynamic stack height. The second DOW loop iterates of the group and retrieves the lag value while also building up the stack for future item lags.



              * some faux data;

              data have (keep=group value duration);
              do group = 1 to 10;
              limit = ceil(4 * ranuni(6));
              put group= limit=;
              do _n_ = 1 to 8 + 10*ranuni(123);
              value = group*10 + _n_;
              duration = 1 + floor(limit*ranuni(123));
              output;
              end;
              end;
              run;

              * dynamic lag provided via hash;

              data want;
              if _n_ = 1 then do;
              retain index lag_value .;
              declare hash lag_stack();
              lag_stack.defineKey('index');
              lag_stack.defineData('lag_value');
              lag_stack.defineDone();
              end;

              do _n_ = 1 by 1 until (last.group);
              set have;
              by group;
              max_duration = max(max_duration, duration);
              end;

              * max_duration within group is the lag lag_stack height;

              * pre-fill missings ;
              do index = 1-max_duration to 0;
              lag_stack.replace(key: index, data: .);
              end;

              do _n_ = 1 to _n_;
              set have;
              lag_stack.replace(key: _n_, data: value);
              lag_stack.find(key: _n_ - max_duration);
              output;
              end;

              drop index;
              run;


              Another technique would involve a fixed length ring-array instead of a hash-stack, but you would need to compute the maximum lag over all groups prior to coding the DATA step using the array.






              share|improve this answer




























                0














                The LAG<n> function is an in-place stack of fixed depth that is specific to it's code use location and thus step state at invocation. The stack is of depth and can not be altered dynamically at runtime.



                A dynamic lag can be implemented in SAS DATA step using a hash object. The double DOW technique allows a group to be measured and then subsequently it's items operated upon.



                Sample code



                This example uses a defines a hash object that maintains a stack of values within a group. A first DOW loop computes the maximum of a field that becomes the dynamic stack height. The second DOW loop iterates of the group and retrieves the lag value while also building up the stack for future item lags.



                * some faux data;

                data have (keep=group value duration);
                do group = 1 to 10;
                limit = ceil(4 * ranuni(6));
                put group= limit=;
                do _n_ = 1 to 8 + 10*ranuni(123);
                value = group*10 + _n_;
                duration = 1 + floor(limit*ranuni(123));
                output;
                end;
                end;
                run;

                * dynamic lag provided via hash;

                data want;
                if _n_ = 1 then do;
                retain index lag_value .;
                declare hash lag_stack();
                lag_stack.defineKey('index');
                lag_stack.defineData('lag_value');
                lag_stack.defineDone();
                end;

                do _n_ = 1 by 1 until (last.group);
                set have;
                by group;
                max_duration = max(max_duration, duration);
                end;

                * max_duration within group is the lag lag_stack height;

                * pre-fill missings ;
                do index = 1-max_duration to 0;
                lag_stack.replace(key: index, data: .);
                end;

                do _n_ = 1 to _n_;
                set have;
                lag_stack.replace(key: _n_, data: value);
                lag_stack.find(key: _n_ - max_duration);
                output;
                end;

                drop index;
                run;


                Another technique would involve a fixed length ring-array instead of a hash-stack, but you would need to compute the maximum lag over all groups prior to coding the DATA step using the array.






                share|improve this answer


























                  0












                  0








                  0







                  The LAG<n> function is an in-place stack of fixed depth that is specific to it's code use location and thus step state at invocation. The stack is of depth and can not be altered dynamically at runtime.



                  A dynamic lag can be implemented in SAS DATA step using a hash object. The double DOW technique allows a group to be measured and then subsequently it's items operated upon.



                  Sample code



                  This example uses a defines a hash object that maintains a stack of values within a group. A first DOW loop computes the maximum of a field that becomes the dynamic stack height. The second DOW loop iterates of the group and retrieves the lag value while also building up the stack for future item lags.



                  * some faux data;

                  data have (keep=group value duration);
                  do group = 1 to 10;
                  limit = ceil(4 * ranuni(6));
                  put group= limit=;
                  do _n_ = 1 to 8 + 10*ranuni(123);
                  value = group*10 + _n_;
                  duration = 1 + floor(limit*ranuni(123));
                  output;
                  end;
                  end;
                  run;

                  * dynamic lag provided via hash;

                  data want;
                  if _n_ = 1 then do;
                  retain index lag_value .;
                  declare hash lag_stack();
                  lag_stack.defineKey('index');
                  lag_stack.defineData('lag_value');
                  lag_stack.defineDone();
                  end;

                  do _n_ = 1 by 1 until (last.group);
                  set have;
                  by group;
                  max_duration = max(max_duration, duration);
                  end;

                  * max_duration within group is the lag lag_stack height;

                  * pre-fill missings ;
                  do index = 1-max_duration to 0;
                  lag_stack.replace(key: index, data: .);
                  end;

                  do _n_ = 1 to _n_;
                  set have;
                  lag_stack.replace(key: _n_, data: value);
                  lag_stack.find(key: _n_ - max_duration);
                  output;
                  end;

                  drop index;
                  run;


                  Another technique would involve a fixed length ring-array instead of a hash-stack, but you would need to compute the maximum lag over all groups prior to coding the DATA step using the array.






                  share|improve this answer













                  The LAG<n> function is an in-place stack of fixed depth that is specific to it's code use location and thus step state at invocation. The stack is of depth and can not be altered dynamically at runtime.



                  A dynamic lag can be implemented in SAS DATA step using a hash object. The double DOW technique allows a group to be measured and then subsequently it's items operated upon.



                  Sample code



                  This example uses a defines a hash object that maintains a stack of values within a group. A first DOW loop computes the maximum of a field that becomes the dynamic stack height. The second DOW loop iterates of the group and retrieves the lag value while also building up the stack for future item lags.



                  * some faux data;

                  data have (keep=group value duration);
                  do group = 1 to 10;
                  limit = ceil(4 * ranuni(6));
                  put group= limit=;
                  do _n_ = 1 to 8 + 10*ranuni(123);
                  value = group*10 + _n_;
                  duration = 1 + floor(limit*ranuni(123));
                  output;
                  end;
                  end;
                  run;

                  * dynamic lag provided via hash;

                  data want;
                  if _n_ = 1 then do;
                  retain index lag_value .;
                  declare hash lag_stack();
                  lag_stack.defineKey('index');
                  lag_stack.defineData('lag_value');
                  lag_stack.defineDone();
                  end;

                  do _n_ = 1 by 1 until (last.group);
                  set have;
                  by group;
                  max_duration = max(max_duration, duration);
                  end;

                  * max_duration within group is the lag lag_stack height;

                  * pre-fill missings ;
                  do index = 1-max_duration to 0;
                  lag_stack.replace(key: index, data: .);
                  end;

                  do _n_ = 1 to _n_;
                  set have;
                  lag_stack.replace(key: _n_, data: value);
                  lag_stack.find(key: _n_ - max_duration);
                  output;
                  end;

                  drop index;
                  run;


                  Another technique would involve a fixed length ring-array instead of a hash-stack, but you would need to compute the maximum lag over all groups prior to coding the DATA step using the array.







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Nov 29 '18 at 15:53









                  RichardRichard

                  9,63721329




                  9,63721329






























                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53521202%2fdynamic-n-in-function-lagn-variable-sas-part2%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown