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

Hi Everyone,

The below codes repeatedly analyze var_1x var_2d var_3e.... and create new variable exit_1x exit_2d exit_3d.... respectively.

I want to make a DO LOOP such as:

Do secondpart from 1x TO 3e;

Could you please help me with this?

Thank you,

HHC

data have;

input value     var_1x     var_2d     var_3e     var_4x;

datalines;

0 2 3 4 5

2 2 2 1 4

4 2 3 1 2

5 3 6 7 8

;run;

data have; set have;

id=_n_;run;

%let secondpart=1x;

data have;

drop i found v2 id2;

set have nobs=totalobs;

i+1;

do j=i to totalobs until (found=1);

set have (keep=value id rename=(value=v2 id=id2)) point=j;

if v2>var_&secondpart then do;

    found=1;

    exit_&secondpart=id2;

    end;

end;

run;

%let secondpart=2d;

data have;

drop i found v2 id2;

set have nobs=totalobs;

i+1;

do j=i to totalobs until (found=1);

set have (keep=value id rename=(value=v2 id=id2)) point=j;

if v2>var_&secondpart then do;

    found=1;

    exit_&secondpart=id2;

    end;

end;

run;

%let secondpart=3e;

data have;

drop i found v2 id2;

set have nobs=totalobs;

i+1;

do j=i to totalobs until (found=1);

set have (keep=value id rename=(value=v2 id=id2)) point=j;

if v2>var_&secondpart then do;

    found=1;

    exit_&secondpart=id2;

    end;

end;

run;

1 ACCEPTED SOLUTION

Accepted Solutions
hhchenfx
Barite | Level 11

I think it works for me.

HHC

data have;

input value     var_1x     var_2d     var_3e     var_4x;

datalines;

0 2 3 4 5

2 2 2 1 4

4 2 3 1 2

5 3 6 7 8

;run;

data have; set have;

id=_n_;run;

%let oldvar= 1x 2d 3e 4x;

%macro test;

%do i=1 %to %sysfunc(countw(&oldvar));

%let secondpart=%scan(&oldvar,&i);

data have;

drop i found v2 id2;

set have nobs=totalobs;

i+1;

do j=i to totalobs until (found=1);

set have (keep=value id rename=(value=v2 id=id2)) point=j;

if v2>var_&secondpart then do;

    found=1;

    exit_&secondpart=id2;

    end;

end;

run;

%end;

%mend;

%test;

View solution in original post

11 REPLIES 11
Reeza
Super User

Bit at a loss as to why arrays won't work instead of macros.

Can you post the expected output based on data and/or logic for output.

RW9
Diamond | Level 26 RW9
Diamond | Level 26

Hi,

Totally agree with Reeza, post what you want as output and how to get there.  Even running the program it makes no sense.  Definitely investigate arrays or lag() function.  Alternatively consider normalizing your data, i.e. have it vertically rather than across.

hhchenfx
Barite | Level 11

Thank you for asking,

One reason I like Do loop is that part of the name of the variable (_1x) will be included in the name of outcome variables.

Moreover, the actual code body is complicate so I find that doing DO LOOP gives me more flexibility.

HHC

Reeza
Super User

Do loops and arrays go hand in hand. Look into vname and vvaluex functions if your interested in variable name m

RW9
Diamond | Level 26 RW9
Diamond | Level 26

But then you are merely creating a rod for your own back so to speak.  Most of the functions have parameters to allow you to work with arrays of variables, but this requires a numeric suffix.  So by avoiding using the numeric suffix you are losing a whole load of functionality?  Please post example test data and required output (and what the required output is meant to be) and we can suggest alternatives.  An example is generating the code which will shrink yours significantly (however based on required output, there may be (and probably is) better ways):

data _null_;

     do I="1x","2d","3e";

     call execute('data have;

                              drop i found v2 id2;

                              set have nobs=totalobs;

                              i+1;     

                              do j=i to totalobs until (found=1);

                                   set have (keep=value id rename=(value=v2 id=id2)) point=j;

                                   if v2>var_'||strip(I)||' then do;

                                        found=1;

                                        exit_'||strip(I)||'=id2;

                                   end;

                             end;

                         run;');

     end;

run;

Loko
Barite | Level 11

Hello,

Reeza and RW9 provided a different and better approach. in case you still want to stick with the DO LOOP:

data have;
input value     var_1x     var_2d     var_3e     var_4x;
datalines;
0 2 3 4 5
2 2 2 1 4
4 2 3 1 2
5 3 6 7 8
;
run;

data have; set have;
id=_n_;
run;


%macro calc (part);

%let i=1;
%let varcur=%scan(&part,&i);

%do %while(&varcur ne );

data have;
drop i found v2 id2;
set have nobs=totalobs;
i+1;

do j=i to totalobs until (found=1);
set have (keep=value id rename=(value=v2 id=id2)) point=j;
if v2>&varcur then do;
    found=1;
    exit_&varcur=id2;
    end;
end;
run;

%let i=%eval(&i+1);
%let varcur=%scan(&part,&i);
%end;

%mend calc;


%calc(var_1x var_2d var_3e)

Astounding
PROC Star

I agree with Reeza.  Here's a little help using arrays:

data want;

  set have nobs=totalobs;

  array vars {3} var_1x var_2d var_3e;

  array exits {3} exit_1x exit_2d exit_3e;

  do _i_=1 to 3;

     found=0;

     do j=1 to totalobs until (found=1);

        set have (keep=value id rename=(value=v2 id=id2)) point=j;

        if v2 > vars{_i_} then do;

           found=1;

           exits{_i_} = id2;

        end;

     end;

  end;

  drop id2 v2;

run;

You get everything in one data set, with no macro language.  Is that the eventual result you are looking for?

hhchenfx
Barite | Level 11

Hi Everyone,

Thank you for helping.

I guess I did not make my case clearer at the beginning.

The reason I want to do DO Loop is to accomplish the below kind of Macro

I do not have SAS with me right now to check if LoKo method works.

HHC


%MACRO doloop;
  %do start=0 %to 2; 
  %do end=0 %to 4 %by 1;
  %do secondpart **** %to ******;   

*-------------------------;
  Code body
*-------------------------;

  %end;
  %end;
  %end;
%mend;

hhchenfx
Barite | Level 11

My idea is to run the analysis for each of the variable

   var_1x var_2d var_3e var_4x;

say:   start=0 and end=0 and var_1x

         start=0 and end=0 and var_2d

       start=0 and end=0 and var_3e

....

.... to

     start=2 and end=4 and var_3e;

     start=2 and end=4 and var_4x;

Thank you for asking.

HHC

%MACRO doloop;

  %do start=0 %to 2; 

  %do end=0 %to 4 %by 1;

  %do secondpart  from 1x, 2d, 3e, 4x;   

*-------------------------;

  Code body

*-------------------------;

  %end;

  %end;

  %end;

%mend;

hhchenfx
Barite | Level 11

I think it works for me.

HHC

data have;

input value     var_1x     var_2d     var_3e     var_4x;

datalines;

0 2 3 4 5

2 2 2 1 4

4 2 3 1 2

5 3 6 7 8

;run;

data have; set have;

id=_n_;run;

%let oldvar= 1x 2d 3e 4x;

%macro test;

%do i=1 %to %sysfunc(countw(&oldvar));

%let secondpart=%scan(&oldvar,&i);

data have;

drop i found v2 id2;

set have nobs=totalobs;

i+1;

do j=i to totalobs until (found=1);

set have (keep=value id rename=(value=v2 id=id2)) point=j;

if v2>var_&secondpart then do;

    found=1;

    exit_&secondpart=id2;

    end;

end;

run;

%end;

%mend;

%test;

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

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
  • 11 replies
  • 1295 views
  • 7 likes
  • 5 in conversation