<?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: Conditional &amp;quot;DO WHERE AND UNTIL&amp;quot; loop possible? in SAS Programming</title>
    <link>https://communities.sas.com/t5/SAS-Programming/Conditional-quot-DO-WHERE-AND-UNTIL-quot-loop-possible/m-p/711830#M219337</link>
    <description>&lt;P&gt;Yes, you can do it with a (conditional) lag:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;You haven't provided a working DATA step with your data, so this is not guaranteed to work:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data want (drop=i _:);
  do i=1 by 1 until (last.id);
    set have;
    by id;
    if result^=' ' then do;
      _last_result=lag(result);
      _last_id=lag(id);   /* ID for last non-missing result*/
      _last_i=lag(i);
      if result='YES' and _last_result=result and _last_id=id and _start_diag_1=. then _start_diag_1=_last_i;
    end;
  end;

  do i=1 by 1 until (last.id);
    set have;
    by id;
    diagnosis=ifn(_start_diag_1=. or i&amp;lt;_start_diag_1,0,1);
    output;
  end;
run;
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Note the lag functions are only run when RESULT^=' ', so the lag(result) will never return a blank (that's what it means when SAS says the lag function is a FIFO queue).&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;But if your data:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Has at least 1 non-missing result for each ID&lt;/LI&gt;
&lt;LI&gt;Has a variable (like SESSION) that never has a duplicate within each ID&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;then this simpler program would be my preference.&amp;nbsp; It doesn't use lags, but the strategy is similar:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data want (drop=_:);

  do until (last.id);
    set have (where=(result^=' '));
    by id result notsorted;
    if _first_session^=. then continue;
    if result='YES' and not (first.result=1 and last.result=1) then _first_session=session;
  end;

  diagnosis=0;
  do until (last.id);
    set have;
    by id;
    if session=_first_session then diagnosis=1;
    output;
  end;

run;
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Because the first DO loop only read non-missing results, it merely has to look for consecutive 'YES' results.&amp;nbsp; Note th e&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;if result='YES' and not (first.result=1 and last.result=1) then _first_session=session;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;merely tests that the current record is a "YES" and it is not a singleton.&lt;/P&gt;</description>
    <pubDate>Sat, 16 Jan 2021 06:15:53 GMT</pubDate>
    <dc:creator>mkeintz</dc:creator>
    <dc:date>2021-01-16T06:15:53Z</dc:date>
    <item>
      <title>Conditional "DO WHERE AND UNTIL" loop possible?</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Conditional-quot-DO-WHERE-AND-UNTIL-quot-loop-possible/m-p/711816#M219330</link>
      <description>&lt;P&gt;Hello,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I have the following hypothetical data scenario:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="MigMaster12_0-1610758375933.png" style="width: 400px;"&gt;&lt;img src="https://communities.sas.com/t5/image/serverpage/image-id/53552i950F844585C6926C/image-size/medium?v=v2&amp;amp;px=400" role="button" title="MigMaster12_0-1610758375933.png" alt="MigMaster12_0-1610758375933.png" /&gt;&lt;/span&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;For each id, a diagnosis (value=1) is made after 2 consecutive "YES" hits, which can also be interspersed with missing results in between the 2 consecutive "YES" hits.&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;If that criteria is met, then the diagnosis will be made at the first of the 2 sessions, and the diagnosis will be kept in all subsequent sessions regardless of the results.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I was thinking to achieve the diagnosis column I desire, a conditional DO loop with WHERE the first instance of Result="YES" and LAG(Result)="YES" can be used. But to my best knowledge of SAS, there isn't such a kind of DO loop? Only DO WHILE &amp;amp; DO UNTIL? And I'm stuck on how to dealing with the missing values that could be in between the consecutive "YES" hits.&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Can anyone chime in with suggestions/advice on how to achieve my desired outcome? Thank you!&lt;/P&gt;</description>
      <pubDate>Sat, 16 Jan 2021 00:59:31 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Conditional-quot-DO-WHERE-AND-UNTIL-quot-loop-possible/m-p/711816#M219330</guid>
      <dc:creator>MigMaster12</dc:creator>
      <dc:date>2021-01-16T00:59:31Z</dc:date>
    </item>
    <item>
      <title>Re: Conditional "DO WHERE AND UNTIL" loop possible?</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Conditional-quot-DO-WHERE-AND-UNTIL-quot-loop-possible/m-p/711830#M219337</link>
      <description>&lt;P&gt;Yes, you can do it with a (conditional) lag:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;You haven't provided a working DATA step with your data, so this is not guaranteed to work:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data want (drop=i _:);
  do i=1 by 1 until (last.id);
    set have;
    by id;
    if result^=' ' then do;
      _last_result=lag(result);
      _last_id=lag(id);   /* ID for last non-missing result*/
      _last_i=lag(i);
      if result='YES' and _last_result=result and _last_id=id and _start_diag_1=. then _start_diag_1=_last_i;
    end;
  end;

  do i=1 by 1 until (last.id);
    set have;
    by id;
    diagnosis=ifn(_start_diag_1=. or i&amp;lt;_start_diag_1,0,1);
    output;
  end;
run;
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Note the lag functions are only run when RESULT^=' ', so the lag(result) will never return a blank (that's what it means when SAS says the lag function is a FIFO queue).&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;But if your data:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Has at least 1 non-missing result for each ID&lt;/LI&gt;
&lt;LI&gt;Has a variable (like SESSION) that never has a duplicate within each ID&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;then this simpler program would be my preference.&amp;nbsp; It doesn't use lags, but the strategy is similar:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data want (drop=_:);

  do until (last.id);
    set have (where=(result^=' '));
    by id result notsorted;
    if _first_session^=. then continue;
    if result='YES' and not (first.result=1 and last.result=1) then _first_session=session;
  end;

  diagnosis=0;
  do until (last.id);
    set have;
    by id;
    if session=_first_session then diagnosis=1;
    output;
  end;

run;
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Because the first DO loop only read non-missing results, it merely has to look for consecutive 'YES' results.&amp;nbsp; Note th e&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;if result='YES' and not (first.result=1 and last.result=1) then _first_session=session;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;merely tests that the current record is a "YES" and it is not a singleton.&lt;/P&gt;</description>
      <pubDate>Sat, 16 Jan 2021 06:15:53 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Conditional-quot-DO-WHERE-AND-UNTIL-quot-loop-possible/m-p/711830#M219337</guid>
      <dc:creator>mkeintz</dc:creator>
      <dc:date>2021-01-16T06:15:53Z</dc:date>
    </item>
    <item>
      <title>Re: Conditional "DO WHERE AND UNTIL" loop possible?</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Conditional-quot-DO-WHERE-AND-UNTIL-quot-loop-possible/m-p/711831#M219338</link>
      <description>&lt;P&gt;This problem is similar to the one posted in your thread&amp;nbsp;&lt;A href="https://communities.sas.com/t5/SAS-Programming/SAS-conditionally-updating-previous-row-s-observation-values/m-p/711241" target="_self"&gt;SAS conditionally updating previous row's observation values&lt;/A&gt;&amp;nbsp;so mu solution there will work here as well &lt;span class="lia-unicode-emoji" title=":slightly_smiling_face:"&gt;🙂&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data want(drop = i r);
   set have curobs = c;
   by id;

   if first.id then diagnosis = 0;

   if diagnosis = 0 and Result = "YES" then do p = (c + 1) by 1;
      if p &amp;gt; n then leave;
      set have (keep = id Result rename = (id = i Result = r)) point = p nobs = n;
      if id ne i then leave;
      if Result = "YES" and r = "NO" then leave;
      if Result = "YES" and r = "YES" then do;
         diagnosis = 1;
         leave;
      end;
   end;

   retain diagnosis;
run;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;H2 class="message-subject"&gt;&lt;SPAN class="lia-message-read"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/H2&gt;
&lt;P&gt;&lt;SPAN class="lia-message-read"&gt;Result:&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;id session Result diagnosis 
1  1              0 
1  4       YES    1 
1  6       YES    1 
1  7       NO     1 
1  9       YES    1 
1  11      YES    1 
1  12             1 
2  1       YES    1 
2  2              1 
2  3              1 
2  7              1 
2  8       YES    1 
2  9       YES    1 &lt;/PRE&gt;
&lt;DIV class="forum-post"&gt;&amp;nbsp;&lt;/DIV&gt;</description>
      <pubDate>Sat, 16 Jan 2021 07:11:49 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Conditional-quot-DO-WHERE-AND-UNTIL-quot-loop-possible/m-p/711831#M219338</guid>
      <dc:creator>PeterClemmensen</dc:creator>
      <dc:date>2021-01-16T07:11:49Z</dc:date>
    </item>
    <item>
      <title>Re: Conditional "DO WHERE AND UNTIL" loop possible?</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Conditional-quot-DO-WHERE-AND-UNTIL-quot-loop-possible/m-p/711891#M219364</link>
      <description>&lt;P&gt;You can simplify the first code I offered by reframing the code from using 2 &lt;FONT face="courier new,courier"&gt;&lt;STRONG&gt;do until (last.id)&lt;/STRONG&gt;&lt;/FONT&gt; loops into a single such loop, by using the HAVE dataset mentioned twice in the set statement.&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data want (drop=_:);
  set have (in=firstpass) have (in=secondpass);
  by id;

  if first.id then call missing (_nr1,_nr2,_first_y_pair);
  if first.id then diagnosis=0;
  retain diagnosis _first_y_pair;

  _nr1+(firstpass=1 and result in ('YES','NO'));
  if _nr1^=lag(_nr1) then 
    if lag(id)=id and lag(result)='YES' and result='YES' and _first_y_pair=. then _first_y_pair=_nr1-1;

  if secondpass;
  _nr2+(result^=' ');

  if _nr2=_first_y_pair then diagnosis=1;
run;&lt;/CODE&gt;&lt;/PRE&gt;</description>
      <pubDate>Sat, 16 Jan 2021 22:02:56 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Conditional-quot-DO-WHERE-AND-UNTIL-quot-loop-possible/m-p/711891#M219364</guid>
      <dc:creator>mkeintz</dc:creator>
      <dc:date>2021-01-16T22:02:56Z</dc:date>
    </item>
    <item>
      <title>Re: Conditional "DO WHERE AND UNTIL" loop possible?</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Conditional-quot-DO-WHERE-AND-UNTIL-quot-loop-possible/m-p/713236#M219994</link>
      <description>&lt;P&gt;Hi there,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Thank you for your suggested solutions; the very last 1 you posted worked.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;However, I do have another do-loop related question that I hope you won't mind taking a look at: if we are using a similar dataset as in this topic, but instead my desired output is where I want to execute a DO function only for the very 1st instance of a "YES" test result:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;data have;&lt;BR /&gt;input id session result desired_output;&lt;BR /&gt;datalines;&lt;BR /&gt;1 4 yes 1&lt;BR /&gt;1 6 yes 0&lt;BR /&gt;1 7 no 0&lt;BR /&gt;1 9 yes 0&lt;BR /&gt;1 12 . 0&lt;BR /&gt;2 1 yes 1&lt;BR /&gt;2 2 . 0&lt;BR /&gt;2 7 . 0&lt;BR /&gt;2 8 yes 0&lt;BR /&gt;2 9 yes 0&lt;BR /&gt;;&lt;BR /&gt;run;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I tried both a DO UNTIL(result="no" or result=.) &amp;amp; a DO WHILE(result="yes"), desired_output=1 code, but that doesn't seem to work.&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Any ideas on how to limit the DO statement to just the 1st instance?&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Thank you again!&lt;/P&gt;</description>
      <pubDate>Thu, 21 Jan 2021 22:13:56 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Conditional-quot-DO-WHERE-AND-UNTIL-quot-loop-possible/m-p/713236#M219994</guid>
      <dc:creator>MigMaster12</dc:creator>
      <dc:date>2021-01-21T22:13:56Z</dc:date>
    </item>
  </channel>
</rss>

