2
votes

I asked this question on RunSubmit too, since SAS Q&A community seems a bit scattered. If this is not appreciated, please let me know.

Is it possible in a data step to return to a previous/certain observation and go from there further through the data set?

To add to the question in case it is still not clear, a small example:

Data set 'work.test' :

name  |   number   
John  |    1      
Jack  |    2  
Jane  |    3     
Jade  |    4       
Ronn  |    5       
Dick  |    6       
Sofy  |    7      
Sady  |    8      
Ruth  |    9      

Data step:

Data _null_;
 set work.test;
 File ...\test.txt;
 put name;
 if number = 5 and counter=3 then do;
   counter = counter+1;
   *return to obs where number = 3* AKA *set obs pointer back to obs with nr=3*;
 end;
run;

*The question is about the part return to obs where number = 1 , not about [and first time] , that is only added so it would not generate and endless loop.*

Additional info:
As it seems to still not be 100% clear what I want to do, I added a bit to the original sample data set and example. Just remember it should be a bit generic and not be fixed code. Conditions might vary later on. But the main question is just: "is it possible to go back to obs=X and go from there when you are at obs=Y and how?"

Background info: This fits into the whole story of creating an xml output using a single table holding the xml flow, where some elements need to be repeated. No, it is not possible using XML map because of old SAS version. No, ODS is also not applicable in this case. Btw, this is just background info because the remark 'I still don't knwo what you try to do' keeps coming up ;)

List of possibilities NOT applicable for my needs:

  • REWIND function (returns only to the first observation)
  • LAG function (to get previous value of variable, not for going back in obs)
  • Using multiple SET statements: this is not generic in the way I need it (ie. some data sets would require 2 loops, others would require 5 loops, thus 5 nested SET statements...)

What COULD work:

  • Use of complete SCL code to go through data step (postponed)
  • POINT option in the SET statement (current try out)
  • Hash tables: still have to do more research as I do not know much about this or how to implement.
2
Does the lag function help you? I'm not quite sure what you're trying to do-Lauren Samuels
I suggest exploring the hash and hash iterator objects, which allow for much more control over where you are within a given set of data.sasfrog
@Louisa: I also found that function, but no it will not really help, since it is a bit similar to the retain statement. Then I would need to "lag" (or "retain" too many values through too many observations) @sasfrog: I will look into it more, but at first sight it is not particularly what I need. Thanks anyway!Yoh
I am now testing with using the POINT option of the SET statement. Only problems I need to solve now is to create and maintain generic variables holding the max number of increments and the current count of those increments.Yoh

2 Answers

1
votes

The SET statement is of an executable type.

/* test data */
data one;
  input name $ num;
cards;
John 1 
Jack 2 
Jane 3 
Jade 4
;
run;

/* output obs until num=3 then output all */
data two;
   do until (num=3 or end1);
      set one end=end1;
      output;
   end;
   do until (end2);
      set one end=end2;
      output;
   end;
   stop;
run;

/* check */
proc print data=two;
run;
/* on lst
Obs    num    name

 1      1     John
 2      2     Jack
 3      3     Jane
 4      1     John
 5      2     Jack
 6      3     Jane
 7      4     Jade
*/
1
votes

The SAS data step primarily operates on one observation at a time, so I believe that sasfrog's comment regarding hash objects might be your best bet. The following code might also be of help (two SET statements); but I'm still not sure what your final expected output is, so this is just a rude example.

data test1;
   set test;
   if number eq 5 then do;
      set test(rename=(name=name2 number=counter) where=(counter=3));
   end;
run;