DATA Step, Macro, Functions and more

how can i recode using array

Accepted Solution Solved
Reply
New Contributor
Posts: 3
Accepted Solution

how can i recode using array

Trying to recode the following into more condensed code

sickday1=S30Q4_30d_1+S30Q5_30d_1+S30Q6_30d_1+S30Q7_30d_1; sickday2=S30Q4_30d_2+S30Q5_30d_2+S30Q6_30d_2+S30Q7_30d_2; sickday3=S30Q4_30d_3+S30Q5_30d_3+S30Q6_30d_3+S30Q7_30d_3;

this format continues until sickday30.

I was able to do so the following with the following in a data statement:

%macro sick (i); sicksday&i. = S30Q4_30d_&i.+S30Q5_30d_&i.+S30Q6_30d_&i.+S30Q7_30d_&i.; %mend; %array(num, values = %numlist(1-30)); %do_over(num, macro=sick);

or with the following code

array sickday {30}; array S30Q4_30d{} S30Q4_30d_1 -- S30Q4_30d_30; array S30Q5_30d{} S30Q5_30d_1--S30Q5_30d_30; array S30Q6_30d{} S30Q6_30d_1--S30Q6_30d_30; array S30Q7_30d{} S30Q7_30d_1--S30Q7_30d_30; do i = 1 to 30; drinksday{i} = S30Q4_30d[i]+S30Q5_30d[i]+S30Q6_30d[i]+S30Q7_30d[i]; end;

 

However my problem arises in that I actually need sickday1- sickday60, but the variables sickday31 to sickday60 are coded as follows: sickday31=S30Q4_60d_1+S30Q5_60d_1+S30Q6_60d_1+S30Q7_60d_1; sickday32=S30Q4_60d_2+S30Q5_60d_2+S30Q6_60d_2+S30Q7_60d_2; etc. where the numbering of the newly created variable no longer matches the endings of the variables used to calculate it. I also think my code to create the first 30 variables could be somewhat improved. I've tried a few ways to do this but nothing is working properly. 


Accepted Solutions
Solution
‎11-28-2016 11:23 AM
Trusted Advisor
Posts: 1,022

Re: how can i recode using array

[ Edited ]

How about a technique of listing all the vars in one long array, then looping through the array by appropriate step sizes?

 

Consider;

 

  array sq {*}  s30q4_30d_1-s30q4_30d_30   s30q4_60d_1-S30q4_60d_30

                      s30q5_30d_1-s30q5_30d_30   s30q5_60d_1-S30q5_60d_30

                      s30q6_30d_1-s30q6_30d_30   s30q6_60d_1-S30q6_60d_30

                      s30q7_30d_1-s30q7_30d_30   s30q7_60d_1-S30q7_60d_30;   /* 4 lists of 60 vars each */

 

   /* Now get 60 sums */

  array sickdays {60} (60*0);

  do S=1 to 60;

     do J=S to dim(sq) by 60;

        sickdays{s}=sickdays{s}+sq{j};

     end;

  end;

 

You could also make array SQ into a 2-dimensional array {60*4}  then sum each column over its 4 rows, then all loops would increment by 1 as in:

 

  do s=1 to 60;

    do r=1 to 4;  sickdays{s}=sickdays{s}+sq{s,r}; end;

  end;

 

Compact code.  No macro needed.

 

Regards,

Mark

View solution in original post


All Replies
New Contributor
Posts: 3

Re: how can i recode using array

I got it to work using the following code but would really like if someone can help with something simpler, perhaps only using arrays without using the %do_over and %array macros.

 

%macro sick (i);
sick day&i. = S30Q4_30d_&i.+S30Q5_30d_&i.+S30Q6_30d_&i.+S30Q7_30d_&i.;
%mend;
%array(num, values = %numlist(1-30));
%do_over(num, macro= sick);
%macro sick 2 (j, k);
sickday&j. = S30Q4_60d_&k.+S30Q5_60d_&k.+S30Q6_60d_&k.+S30Q7_60d_&k.;
%mend;
%array(num2, values = %numlist(31-60));
%array(num3, values = %numlist(1-30));
%do_over(num2 num3, macro= sick2);

Super User
Posts: 19,837

Re: how can i recode using array

To be honest, not being able to read your code isn't helping your question at all.

 

Rather than dealing with all 30 vars and how many every summaries, can you simplify your problem to maybe 5 and the corresponding sums?Adding some sample data to test with would be helpful as well.

 

I'm 99% certain you can do this with arrays.

Solution
‎11-28-2016 11:23 AM
Trusted Advisor
Posts: 1,022

Re: how can i recode using array

[ Edited ]

How about a technique of listing all the vars in one long array, then looping through the array by appropriate step sizes?

 

Consider;

 

  array sq {*}  s30q4_30d_1-s30q4_30d_30   s30q4_60d_1-S30q4_60d_30

                      s30q5_30d_1-s30q5_30d_30   s30q5_60d_1-S30q5_60d_30

                      s30q6_30d_1-s30q6_30d_30   s30q6_60d_1-S30q6_60d_30

                      s30q7_30d_1-s30q7_30d_30   s30q7_60d_1-S30q7_60d_30;   /* 4 lists of 60 vars each */

 

   /* Now get 60 sums */

  array sickdays {60} (60*0);

  do S=1 to 60;

     do J=S to dim(sq) by 60;

        sickdays{s}=sickdays{s}+sq{j};

     end;

  end;

 

You could also make array SQ into a 2-dimensional array {60*4}  then sum each column over its 4 rows, then all loops would increment by 1 as in:

 

  do s=1 to 60;

    do r=1 to 4;  sickdays{s}=sickdays{s}+sq{s,r}; end;

  end;

 

Compact code.  No macro needed.

 

Regards,

Mark

Super User
Posts: 19,837

Re: how can i recode using array

@mkeintz small typo in the variable names - second and fourth set starts with 30 rather than S30?

Trusted Advisor
Posts: 1,022

Re: how can i recode using array

@Reeza

 

thank you. now corrected.

New Contributor
Posts: 3

Re: how can i recode using array

Thank you, was very helpful. I was stuck thinking about the problem in a certain way and your solution is simple but just what I needed.

☑ This topic is solved.

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

Discussion stats
  • 6 replies
  • 244 views
  • 1 like
  • 3 in conversation