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

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. 

1 ACCEPTED SOLUTION

Accepted Solutions
mkeintz
PROC Star

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

--------------------------
The hash OUTPUT method will overwrite a SAS data set, but not append. That can be costly. Consider voting for Add a HASH object method which would append a hash object to an existing SAS data set

Would enabling PROC SORT to simultaneously output multiple datasets be useful? Then vote for
Allow PROC SORT to output multiple datasets

--------------------------

View solution in original post

6 REPLIES 6
rs84
Calcite | Level 5

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);

Reeza
Super User

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.

mkeintz
PROC Star

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

--------------------------
The hash OUTPUT method will overwrite a SAS data set, but not append. That can be costly. Consider voting for Add a HASH object method which would append a hash object to an existing SAS data set

Would enabling PROC SORT to simultaneously output multiple datasets be useful? Then vote for
Allow PROC SORT to output multiple datasets

--------------------------
Reeza
Super User

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

mkeintz
PROC Star

@Reeza

 

thank you. now corrected.

--------------------------
The hash OUTPUT method will overwrite a SAS data set, but not append. That can be costly. Consider voting for Add a HASH object method which would append a hash object to an existing SAS data set

Would enabling PROC SORT to simultaneously output multiple datasets be useful? Then vote for
Allow PROC SORT to output multiple datasets

--------------------------
rs84
Calcite | Level 5

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.

sas-innovate-2024.png

Don't miss out on SAS Innovate - Register now for the FREE Livestream!

Can't make it to Vegas? No problem! Watch our general sessions LIVE or on-demand starting April 17th. Hear from SAS execs, best-selling author Adam Grant, Hot Ones host Sean Evans, top tech journalist Kara Swisher, AI expert Cassie Kozyrkov, and the mind-blowing dance crew iLuminate! Plus, get access to over 20 breakout sessions.

 

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
  • 6 replies
  • 884 views
  • 1 like
  • 3 in conversation