BookmarkSubscribeRSS Feed
RobF
Quartz | Level 8

Working with the following toy dataset, I'm trying to create code which will automatically calculate two-way interaction variables for a given set of main effects named "black", "white" and "red".

 

data test;
input black white red;
cards;
10 20 30
40 50 60
70 80 90
;
run;

proc contents data=test out=varlist(keep=name);
run;

data _null_;
length allvars $20;
retain allvars ' ';
set varlist end=eof;
allvars = trim(left(allvars))||' '||left(name);
if eof then call symput('varlist', allvars);
run;
%put &varlist;
/*
black red white
*/

%macro create_interaction_vars();
	data test;
	set test;
		%let separator_s =%str( );
		%do i=1 %to 3;
			%let v&i = %scan(&varlist, &i, %str( ));
		%end;
		%do i=1 %to 3;
			%do j=1 %to 3;
				%if &i <= &j %then %goto continue; 
					data test;
					set test;
						w&i.&j = &&v&i.*&&v&j;
						rename w&i.&j = "&v&i._&v&j_int";
					run;
					%continue:
			%end;
		%end;
	run;
%mend;
%create_interaction_vars();

 

 

I have no problems creating interactions variables named w12, w13, and w23. However, I'd like the interaction terms to have more informative names created from the main effect terms such as: "white_red_int", "white_black_int", and "red_black_int", but am getting tied up when it comes to concatenating two macro variable names.

 

Any help is much appreciated, thanks!

 

Robert

6 REPLIES 6
Reeza
Super User

Are you familiar with the SAS shortcut notation for creating two way interactions. 

 

You can use the | with @N to create your two way interactions. I can't find the documentation but I'm sure it's in there somewhere.

 

Here's an example using SASHELP.CARS

 

proc glm data=sashelp.cars;
model weight = invoice | length | mpg_city | mpg_highway @2;
run;
 
RobF
Quartz | Level 8

Reeza -

 

Yes, I've used that feature and it's quite handy.

 

In this case I have a lot of variables & the dataset will be exported to a text file for analysis in other programs. Otherwise I'd use the | and n@ option.

 

Robert

PGStats
Opal | Level 21

You can build on @Reeza's suggestion with proc GLMMOD and get your design matrix directly into a dataset. Just add your dependent variable to your dataset :

 

data test;
input id green black white red;
cards;
1 2.1 10 20 30
2 3.2 40 50 60
3 4.3 70 80 90
;

proc glmmod data=test outdesign=testd outparm=testp;
model green = black | white | red @2 / noint;
weight id; /* Just copy this variable */
run;

proc sql;
select 
    cats("Col", _COLNUM_, "=", translate(EFFNAME, "_", "*")),
    cats("Col", _COLNUM_, "=""", EFFNAME, """")
    into :renameVars separated by " ", :labelVars separated by " "
from testp;
quit;

data myDesign;
set testd;
rename &renameVars;
label &labelVars;
run;

proc print data=myDesign noobs label; run;


PG
RobF
Quartz | Level 8

Thanks PGStats, this works great!

 

There must still be a way to combine two macro variable names like "black" and "white" into a single varibale name "black_white_int", but getting the macro code syntax right with the ampersands and quotation marks has always been tricky for me.

RobF
Quartz | Level 8

Here's another solution to creating interaction variables that avoids macro programming.

 

Create a variable list of the main effects of interest from proc contents, then accumulate all of the interaction variable creation data step statements into one long macro variable.

 

For example, to create the interaction variables green_red_int, black_red_int, and white_red_int, run the following code:

 

data test;
input id green black white red;
cards;
1 2.1 10 20 30
2 3.2 40 50 60
3 4.3 70 80 90
;

proc contents data=test out=varlist(keep=varnum name) order=varnum;
run;
proc sort data=varlist;
	by varnum;
run;
data varlist;
set varlist;
	if varnum in(2:4);
run;

data _null_;
length allvars $90;
retain allvars;
set varlist end=eof;
	allvars =trim(left(allvars))||' '||trim(name)||'_red_int = '||trim(name)||'*red;';
	if eof then call symput('interactions', allvars);
run;
%put &interactions;

data test2;
set test;
	&interactions;
run;

SAS Innovate 2025: Register Now

Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
Sign up by Dec. 31 to get the 2024 rate of just $495.
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.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 6 replies
  • 1518 views
  • 0 likes
  • 3 in conversation