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
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) ;
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.
@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.
Oh wait, i guess you're right. I was looking at 2003 only, not 2003mp and 2003ms.
Thanks.
@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.
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) ;
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.
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.