BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
someone_new
Fluorite | Level 6
Hi,

Wanna ask any efficient ways to do same operations on multiple columns?

Example:
I have a macro named "%fun" and column names of
A1 A2 A3 A4 A5 A6 B1 B2 B3 B4 B5

So i wish to loop the macro %fun across columns A4 to B4, any ideas how to code this? (ps. In real dataset, I have about 300 columns)
1 ACCEPTED SOLUTION

Accepted Solutions
Kurt_Bremser
Super User
%let vars = a b c;

data want;
set have;
array have {*} &vars.;
array ret {%sysfunc(countw(&vars.))} _temporary_;
do i = 1 to dim(have);
  if have{i} ne .
  then ret{i} = have{i};
  else have{i} = ret{i};
end;
drop i;
run;

Untested, posted from my tablet. If it works, all you have to do is to populate the macro variable.

View solution in original post

12 REPLIES 12
someone_new
Fluorite | Level 6
Basically the macro %fun retain a previous value and place into missing value or cells
Kurt_Bremser
Super User

That can be done in a single data step, using an array for the variables and a temporary array of same size for the retained values.

All you need to create first is a macro variable with the variable names, for the array definitions; the size of the temporary array can be determined from that with %sysfunc(countw()).

Show the code you run for a single variable, and we'll show you how to expand it.

someone_new
Fluorite | Level 6
%macro fun(variable) ;
retain _&variable;
if &variable ^=. then _&variable = &variable;
else &variable = _&variable;
drop _&variable;
%mend;
Kurt_Bremser
Super User
%let vars = a b c;

data want;
set have;
array have {*} &vars.;
array ret {%sysfunc(countw(&vars.))} _temporary_;
do i = 1 to dim(have);
  if have{i} ne .
  then ret{i} = have{i};
  else have{i} = ret{i};
end;
drop i;
run;

Untested, posted from my tablet. If it works, all you have to do is to populate the macro variable.

someone_new
Fluorite | Level 6
How about range of columns instead of %let vars method?
someone_new
Fluorite | Level 6
Yours solution works perfectly thank you so muchhhhhh you save my day thank you!!!
Tom
Super User Tom
Super User

@someone_new wrote:
How about range of columns instead of %let vars method?

If you want to use a variable list (var1-var10 for example) instead of naming each variable then you need to modify the data step to just make the temporary array large enough for any possible real use. 

 

%let vars = a b var1-var20 firstvar-numeric-lastvar;
...
array have {*} &vars.;
array ret {1000} _temporary_;
Kurt_Bremser
Super User

You need to know the number of variables before you enter the data step, to correctly define the temporary array. So you will need to determine the list of variables, anyway.

 


@someone_new wrote:
How about range of columns instead of %let vars method?

 

Tom
Super User Tom
Super User
You just need to know an upper bound on the number the number of variables. The size of the temporary array does not matter as long as it is at least as large as the actual array.
someone_new
Fluorite | Level 6
Hi @Kurt_Bremser i have new challenging problem mind help me solve it? I have posted in my profile

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