Uneven do loops

Solved
Frequent Contributor
Posts: 128

Uneven do loops

Hi all,

So I'm trying to recode this into two do loops, but as you can see the year and the count numbers don't increment equally.

data test;

set test2;

if _c4_ ne -999 then y2003mp=_c4_;

if _c5_ ne -999 then y2003ms=_c5_;

...

if _c28_ ne -999 then y2015mp=_c28_;

if _c29_ ne -999 then y2015ms=_c29_;

run;

How can i replace the 4-29 with one do =loop and the 2003-2015 with a second do loop?

Thanks

Megan

Accepted Solutions
Solution
‎06-09-2017 04:01 PM
Posts: 1,309

Re: Uneven do loops

The problem is that your varnames don't conform to the normal array declaration syntax, (as in    array X {*} x1-x7). And unless you can guarantee the physical order of the vars in the PDF, the double dash convention (array c {*} _C4_ -- _C29_) might not be an option:

This is a good case for a list generating macro, as in:

``````%macro array(prefix=%str(),suffix=%str(),from=1,to=1);
%do I=&from %to &to; &prefix.&I.&suffix %end;
%mend array;

options mprint;

data want;
set have;
array c {} %array(prefix=_c,from=4,to=29,suffix=_);
array mp {} %array(prefix=y,from=2003,to=2015,suffix=mp);
array ms {} %array(prefix=y,from=2003,to=2015,suffix=ms);
do I=1 to 13;
if c{2*I-1}^= -999 then mp{I}=c{2*I-1};
if c{2*I}^= -999 then ms{I}=c{2*I};
end;
run;``````

Note if FROM has fewer digits than TO  (i.e. from=80, to=120), Iand you really want something like three digits  throughout (  X080P ...X120P), you can use the %array macro twice, as in

Array  myvars {*}   %array(prefix=X0,from=80,to=99,suffix=P)  %array(prefix=X,from=100,to=120,suffix=P) ;

All Replies
Posts: 3,845

Re: Uneven do loops

You need ARRAYS
array C[*] _C4_--_C29_;
array Y[*] y2003mp y2003ms ... y2015mp y2015ms;
Look at the online documentation for details of how to use arrays.
Frequent Contributor
Posts: 128

Re: Uneven do loops

Thanks, i just didn't want to type all the fields out.  Also i'm not sure how arrays would handle the unevenness either.  Using 1 from the first array and 2 from the second and then the 2nd from the 1st array and the 3rd and 4th from the second.

Still not sure how that would work.

Super User
Posts: 13,304

Re: Uneven do loops

[ Edited ]

MeganE wrote:

Thanks, i just didn't want to type all the fields out.  Also i'm not sure how arrays would handle the unevenness either.  Using 1 from the first array and 2 from the second and then the 2nd from the 1st array and the 3rd and 4th from the second.

Still not sure how that would work.

Why would you "Using 1 from the first array and 2 from the second" ? Your example didn't show anything like that.

You would be using the first from each array , then the second.

array C[*] _C4_--_C29_;
array Y[*] y2003mp y2003ms ... y2015mp y2015ms;

do i= 1 to dim(c);

if c[i] ne -999 then y[i] = c[i];

end;

Just make sure that the C array elements and the Y array elements are listed such that they align.

Frequent Contributor
Posts: 128

Re: Uneven do loops

Oh wait, i guess you're right.  I was looking at 2003 only, not 2003mp and 2003ms.

Thanks.

Super User
Posts: 13,304

Re: Uneven do loops

MeganE wrote:

Oh wait, i guess you're right.  I was looking at 2003 only, not 2003mp and 2003ms.

Thanks.

I actually use the Editor to help align things to double check I have matching elements. Here's a short example

```array rhd rhd1-rhd6 rhd9-rhd18 hisp;
array rh  rh1 -rh6  rh9 -rh18  ETHNIC;```

Notice that the dashes in the range lists align so it is easy to compare the index values (even if they may not match) and the variable names first characters align so I can tell that the HISP variable is going to be used with ETHNIC. The challenge is bit more fun with arrays of 50 or more variables where I really don't want one long line of text and have to break the array definitions into multiple lines for readability but the idea is the same: Visually align the code to make sure the number of variables matches.

Solution
‎06-09-2017 04:01 PM
Posts: 1,309

Re: Uneven do loops

The problem is that your varnames don't conform to the normal array declaration syntax, (as in    array X {*} x1-x7). And unless you can guarantee the physical order of the vars in the PDF, the double dash convention (array c {*} _C4_ -- _C29_) might not be an option:

This is a good case for a list generating macro, as in:

``````%macro array(prefix=%str(),suffix=%str(),from=1,to=1);
%do I=&from %to &to; &prefix.&I.&suffix %end;
%mend array;

options mprint;

data want;
set have;
array c {} %array(prefix=_c,from=4,to=29,suffix=_);
array mp {} %array(prefix=y,from=2003,to=2015,suffix=mp);
array ms {} %array(prefix=y,from=2003,to=2015,suffix=ms);
do I=1 to 13;
if c{2*I-1}^= -999 then mp{I}=c{2*I-1};
if c{2*I}^= -999 then ms{I}=c{2*I};
end;
run;``````

Note if FROM has fewer digits than TO  (i.e. from=80, to=120), Iand you really want something like three digits  throughout (  X080P ...X120P), you can use the %array macro twice, as in

Array  myvars {*}   %array(prefix=X0,from=80,to=99,suffix=P)  %array(prefix=X,from=100,to=120,suffix=P) ;

☑ This topic is solved.