DATA Step, Macro, Functions and more

SET statement processing in ARRAYS

Accepted Solution Solved
Reply
New Contributor
Posts: 2
Accepted Solution

SET statement processing in ARRAYS

[ Edited ]

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;

Accepted Solutions
Solution
4 weeks ago
Trusted Advisor
Posts: 1,256

Re: SET statement processing in ARRAYS

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


All Replies
Solution
4 weeks ago
Trusted Advisor
Posts: 1,256

Re: SET statement processing in ARRAYS

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.

New Contributor
Posts: 2

Re: SET statement processing in ARRAYS

Posted in reply to FreelanceReinhard
Thanks a lot FreelanceReinhard - Indeed exactly what I was looking for!
Super User
Posts: 10,279

Re: SET statement processing in ARRAYS

[ Edited ]

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;
---------------------------------------------------------------------------------------------
Maxims of Maximally Efficient SAS Programmers
How to convert datasets to data steps
How to post code
Super User
Posts: 10,279

Re: SET statement processing in ARRAYS

BTW there are no arrays in your question, only do loops.

---------------------------------------------------------------------------------------------
Maxims of Maximally Efficient SAS Programmers
How to convert datasets to data steps
How to post code
Trusted Advisor
Posts: 1,256

Re: SET statement processing in ARRAYS

[ Edited ]

@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.

☑ This topic is solved.

Need further help from the community? Please ask a new question.

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