Hi there,
I have 50 categorical variables for which I need to create dummy variables for each level of response. For instance, variable Q1 has 3 levels: 1,2,3. The macro DUMMYLEVEL below will create 3 dummy variables for Q1: Q1_1, Q1_2, and Q1_3.
My codes below-- which invokes the macro DUMMYLEVEL twice in the DATA step-- produces the following error message:
"ERROR 124-185: The variable D has already been defined."
This error only occurs when the macro DUMMYLEVEL is called more than once in the DATA step. Anybody have experience working around this error to achieve my goal of creating dummy variables for 50 categorical variables? Thank you!
/* Macro to create dummy variables for ROOT variable with NUM levels */
%MACRO DUMMYLEVEL (ROOT= , NUM= );
ARRAY D(*) &ROOT._1 - &ROOT._&NUM. (&NUM.*0);
IF &ROOT. NE . THEN D(&ROOT.)= 1;
OUTPUT;
IF &ROOT. NE . THEN D(&ROOT.)= 0;
%MEND;
/* Sample DATA step: call macro DUMMYLEVEL twice */
DATA OUT;
SET IN (KEEP= ID Q1--Q50);
%Dummylevel (root= Q1, num= 3);
%Dummylevel (root= Q2, num= 2);
RUN;
Adapt your macro to create individually named arrays for each invocation:
/* Macro to create dummy variables for ROOT variable with NUM levels */
%macro dummylevel(root,num);
array d_&root.(*) &root._1 - &root._&num.;
do d__i = 1 to dim(d_&root.);
d_&root.{d__i) = 0;
end;
if &root. ne . then d_&root.(&root.)= 1;
drop d__i;
%mend;
Also note that I removed the output and reset to 0, and instead intialized thé whole array for each data step iteration. Otherwise you'd multiply your dataset observations.
In example code:
data have;
input ID Q1 Q2;
cards;
1 2 .
2 1 1
3 2 2
;
run;
data want;
set have;
%dummylevel(Q1,3);
%dummylevel(Q2,3);
run;
proc print;run;
you then get this result:
Obs ID Q1 Q2 Q1_1 Q1_2 Q1_3 Q2_1 Q2_2 Q2_3 1 1 2 . 0 1 0 0 0 0 2 2 1 1 1 0 0 1 0 0 3 3 2 2 0 1 0 0 1 0
Edit: Corrected to the proper macrocode.
You need a unique array declaration for each macro call.
Although you can do this, have you looked into some of the other methods? Here are some references that illustrate alternatives.
http://blogs.sas.com/content/iml/2016/02/22/create-dummy-variables-in-sas.html
Adapt your macro to create individually named arrays for each invocation:
/* Macro to create dummy variables for ROOT variable with NUM levels */
%macro dummylevel(root,num);
array d_&root.(*) &root._1 - &root._&num.;
do d__i = 1 to dim(d_&root.);
d_&root.{d__i) = 0;
end;
if &root. ne . then d_&root.(&root.)= 1;
drop d__i;
%mend;
Also note that I removed the output and reset to 0, and instead intialized thé whole array for each data step iteration. Otherwise you'd multiply your dataset observations.
In example code:
data have;
input ID Q1 Q2;
cards;
1 2 .
2 1 1
3 2 2
;
run;
data want;
set have;
%dummylevel(Q1,3);
%dummylevel(Q2,3);
run;
proc print;run;
you then get this result:
Obs ID Q1 Q2 Q1_1 Q1_2 Q1_3 Q2_1 Q2_2 Q2_3 1 1 2 . 0 1 0 0 0 0 2 2 1 1 1 0 0 1 0 0 3 3 2 2 0 1 0 0 1 0
Edit: Corrected to the proper macrocode.
Thank you for your help-- the macro worked perfectly. For some reason, your original macro is not showing on this page. As a reference for others, I've retyped it here:
%macro dummylevel (root= , num=);
array d_&root. (*) &root._1 - &root._&num.;
do d__i = 1 to dim(d_&root.);
d_&root.{d__i} = 0;
end;
if &root. ne . then d_&root.(&root.) = 1;
drop d__i;
%mend;
Sorry, I am not sure why all that is necessary? Arrays can be defined with multiple dimensions, its then just the need to get your variables in the necessary order in the define context:
data out; set in (keep=id q1--q50); array resp{50,3) $20; do i=1 to 50; resp{i,1}=...; resp{i,2}=...; ... end; run;
And please dont code in all upper case, its one of the worse visual things to do code.
Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.
Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.
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.