BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
Tom
Super User Tom
Super User

To convert a list in macro variable into a series of observations just use a DO loop.

 

%let list=a b c d;
data list;
  length index 8 name $32 ;
  do index=1 to countw("&list");
    name=scan("&list",index);
    output;
  end;
run;  

 

But why?

To generate a sum many variables just use arrays.

 

 

%let source=height weight age;
%let target=c_height c_weight c_age;
proc sort data=sashelp.class out=have;
  by sex;
run;

data want;
  do until(last.sex);
    set have ;
    by sex;
    array in &source;
    array out ⌖
    do index=1 to dim(in);
       out[index]=sum(out[index],in[index]);
    end;
    output;
  end;
  drop index;
run;

If you want to generate the target names from the source names you could use something like:

%let target=c_%sysfunc(tranwrd(&source,%str( ),%str( c_)));

 

s_lassen
Meteorite | Level 14

As I read you initial macro, it does this:

%macro cumsum1by(ds, var, byvar); 
  data &ds.(DROP = );
  set &ds.; 
  by &byvar.; 
  RETAIN &var._csum ; 
  &var._csum=coalesce(&var.,0)+coalesce(&var._csum,0) ; 
  IF FIRST.&byvar. THEN &var._csum = coalesce(&var.,0) ;
RUN ;
%mend;

And you want to do that with a variable list instead of a single variable. Something like this may work:

%macro cumsum1by(ds, vars, byvar,drop=,out=&ds); 
  %local i var lastby n_vars;
  %let lastby=%scan(&byvar,%sysfunc(countw(&byvar)));
  %let n_vars=%sysfunc(countw(&vars));
  data &out(DROP=&drop );
    set &ds.; 
    by &byvar.; 
    if first.&lastby then do;
      %do i=1 %to &n_vars;
         %let var=%scan(&vars,&i);
         &var._csum=0;
         %end;
      end;
     %do i=1 %to &n_vars;
         %let var=%scan(&vars,&i);
         &var._csum+&var;
         %end;
 RUN ;
%mend;

I put in the DROP= parameter because it looked like you had thought about creating one. And I put in an OUT= parameter; although your initial macro overwrites the original dataset (which is also the default in the new version), you may want to do something else.

 

And then I changed the use of RETAIN and COALESCE to a SUM statement (&var._csum+&var;), which is very nifty for stuff like this: the variable added gets automatically coalesced with zero, and the receiving variable gets automatically retained.

 

I also put in a calculation of the last of a BY variable list (&LAST_BY), in case you want to use more than one BY variable.

 

So an example of a call could be this

cumsum1by(work.have,cash owed left,client_id month,drop=a c,out=test);

which will summarize the variables CASH, OWED and LEFT from WORK.HAVE by CLIENT_ID and MONTH, and output it to TEST, dropping variables A and C.

 

sas-innovate-2024.png

Available on demand!

Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.

 

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
  • 17 replies
  • 1108 views
  • 2 likes
  • 6 in conversation