BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
bearda
Obsidian | Level 7

Hey,

 

I have a rather simple problem which does have many ways to overcome but in the context I'm working at it would be more than appreciated to be able to solve the issue with the "reset" method explained below:

 

* Create testdata ;
data testdata;
    do value = 1 to 6;
        if value <= 3 
            then keyval = "key1";
            else keyval = "key2";
        output;
    end;
run;

* Create index for testdata ;
proc datasets lib = work;
    modify testdata;
    index create keyval;
run;

* Result as expected: key1 is found twice and key2 once ;
data result_valid;
    if 0 then set testdata;
    do keyval = "key1", "key2", "key1";
        do until(_iorc_ ne 0);
            set testdata key = keyval;
            iorc = _iorc_; /* Just for test purposes, remove if condition below to test it */
            if _iorc_ = 0 then output;
        end;
    end;
    stop;
run;

* But subsequent identical keyval -values does not provide expected result ;
*   - In the background key "pointer" is not reset after the previous search ;
*   -- Question is: Is there any way to reset it? ;
data result_invalid;
    if 0 then set testdata;
    do keyval = "key1", "key1", "key2";
        do until(_iorc_ ne 0);
            set testdata key = keyval;
            iorc = _iorc_; /* Just for test purposes, remove if condition below to test it */
            if _iorc_ = 0 then output;
        end;
    end;
    stop;
run;

* Similar processing happens with simple data step: Reult_simple contains only one row ;
data result_simple;
    do i = 1 to 3;
        set sashelp.cars(obs = 1);
        output;
    end;
run;

* But with point processing it works ;
data result_point;
    do i = 1, 1, 1;
        set sashelp.cars point = i;
        output;
    end;
    stop;
run;

 

Workaround tried:

* Attempt to reset "pointer" by calling a dummy key if subsequent keys are found ;
* -> No success ;
data result_invalid;
    if 0 then set testdata;
    do keyval = "key1", "key1", "key2";
        if prev_key = keyval then do;
            * Try to reset pointer for "key1" ;
            _tmp_key    = keyval;
            keyval      = "dumm";
            set testdata key = keyval;
            prev_key = _tmp_key;
        end;
        else prev_key = keyval;

        do until(_iorc_ ne 0);
            set testdata key = keyval;
            iorc = _iorc_; /* Just for test purposes, remove if condition below to test it */
            if _iorc_ = 0 then output;
        end;
    end;
    stop;
run;
1 ACCEPTED SOLUTION

Accepted Solutions
FreelanceReinh
Jade | Level 19

Hi @bearda and welcome to the SAS Support Communities!

 

I think, the KEYRESET= option (new in SAS 9.4) is exactly what you are looking for.

 

Example:

data result_valid2;
    if 0 then set testdata;
    do keyval = "key1", "key1", "key2";
        reset=1;
        do until(_iorc_ ne 0);
            *put 'Before SET: ' reset= _iorc_=;
            set testdata key = keyval keyreset=reset;
            *put 'After SET: ' reset= _iorc_=;
            if _iorc_ = 0 then output;
        end;
    end;
    _error_=0; /* avoids unwanted log message */
    stop;
run;

I have commented out two diagnostic PUT statements which show that variable RESET is automatically reset to 0 (otherwise an infinite loop would be likely to occur!). Although important, this is not clearly stated in the documentation, as far as I see.

View solution in original post

5 REPLIES 5
FreelanceReinh
Jade | Level 19

Hi @bearda and welcome to the SAS Support Communities!

 

I think, the KEYRESET= option (new in SAS 9.4) is exactly what you are looking for.

 

Example:

data result_valid2;
    if 0 then set testdata;
    do keyval = "key1", "key1", "key2";
        reset=1;
        do until(_iorc_ ne 0);
            *put 'Before SET: ' reset= _iorc_=;
            set testdata key = keyval keyreset=reset;
            *put 'After SET: ' reset= _iorc_=;
            if _iorc_ = 0 then output;
        end;
    end;
    _error_=0; /* avoids unwanted log message */
    stop;
run;

I have commented out two diagnostic PUT statements which show that variable RESET is automatically reset to 0 (otherwise an infinite loop would be likely to occur!). Although important, this is not clearly stated in the documentation, as far as I see.

bearda
Obsidian | Level 7
Thanks a lot FreelanceReinhard - Indeed exactly what I was looking for!
Kurt_Bremser
Super User

I can give you at least one important hint for the working of the data step:

data result_simple;
    do i = 1 to 3;
        set sashelp.cars(obs = 1);
        output;
    end;
run;

In the first iteration of the do loop, one observation is read; since you set the dataset option obs=1, this is the only observation you will get.

In the second iteration, you try to read past that observation, and the internal data step logic immediately "catapults" you to the end of the data step and terminates it. Add some put statements for debugging purposes, and look at the log:

data result_simple;
    do i = 1 to 3;
        put "before set: " i=;
        set sashelp.cars(obs = 1);
        put "after set: " i=;
        output;
    end;
run;

and then try:

data result_simple;
set sashelp.cars(obs = 1);
do i = 1 to 3;
  output;
end;
run;
FreelanceReinh
Jade | Level 19

@bearda: The reason why your "workaround" does not work is that the two SET statements in your data step which are executed (unlike the third one with "if 0 then ...") have the same effect as if there were two completely independent virtual datasets TESTDATA1 and TESTDATA2, both identical to dataset TESTDATA (cf. this paper on the DOW loop, p. 10). So, resetting the pointer for one of the "two" datasets has no impact at all on how the SET statement acts on the other.

sas-innovate-2024.png

Don't miss out on SAS Innovate - Register now for the FREE Livestream!

Can't make it to Vegas? No problem! Watch our general sessions LIVE or on-demand starting April 17th. Hear from SAS execs, best-selling author Adam Grant, Hot Ones host Sean Evans, top tech journalist Kara Swisher, AI expert Cassie Kozyrkov, and the mind-blowing dance crew iLuminate! Plus, get access to over 20 breakout sessions.

 

Register now!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 5 replies
  • 914 views
  • 5 likes
  • 3 in conversation