Resolving Value Differences among Duplicates

Eliminate Cookie-Cutter Code
with %wordLoop
[email protected]
11
Def. of CCC – How It Is Created
Write a short chunk of SAS code
 Copy, paste, edit
 Copy, paste, edit
 Copy, paste, edit
 … (until the list in mind is exhausted)

2
Why diss Cookie-Cutter Code?
Now vs. later
vs.
33
%wordLoop Signature
%wordLoop( wordList=<>, contentMacro=<>);
Where:
wordList => values to loop over, e.g.
data set names
contentMacro => code applied on each loop
4
Example Code
Select a subset of observations from each
of N datasets
 Create N new suitably-named datasets
 Subset specified by finderFileDs
 Why? subset analysis, data transfer,
removal of patients from study

5
Example Cookie-Cutter Code
DATA patientDs_subset;
MERGE patientDs(in=in1) finderFileDs(in=in2);BY id;
IF in1 and in2;
RUN;
DATA consultDs_subset;
MERGE consultDs(in=in1) finderFileDs(in=in2);BY id;
IF in1 and in2;
RUN;
DATA hospStayDs_subset;
MERGE hospStayDs(in=in1) finderFileDs(in=in2);BY id;
IF in1 and in2;
RUN;
DATA eventsDs_subset;
MERGE eventsDs(in=in1) finderFileDs(in=in2);BY id;
IF in1 and in2;
RUN;
DATA drugsDs_subset;
MERGE drugsDs(in=in1) finderFileDs(in=in2);BY id;
IF in1 and in2;
RUN;
6
Ex. CCC showing Substitutions
DATA patientDs_subset;
MERGE patientDs(in=in1) finderFileDs(in=in2);BY id;
IF in1 and in2;
RUN;
DATA consultDs_subset;
MERGE consultDs(in=in1) finderFileDs(in=in2);BY id;
IF in1 and in2;
RUN;
DATA hospStayDs_subset;
MERGE hospStayDs(in=in1) finderFileDs(in=in2);BY id;
IF in1 and in2;
RUN;
DATA eventsDs_subset;
MERGE eventsDs(in=in1) finderFileDs(in=in2);BY id;
IF in1 and in2;
RUN;
DATA drugsDs_subset;
MERGE drugsDs(in=in1) finderFileDs(in=in2);BY id;
IF in1 and in2;
RUN;
7
Repeating Pattern
DATA <Ds from list>_subset;
MERGE <Ds from list>(in=in1)
finderFileDs(in=in2);
BY id;
IF in1 and in2;
RUN;
Ds list:
patientDs consultDs hospStayDs
eventDs drugDs
8
Liabilities of CCC
Cut-paste-edit errors
 Bulky and hard to read
 Tedious to change implementation
 List is hidden
 List tedious to change

Make a macro of repeating element?
9
Ex. with Macro Definition
%MACRO getSubset(ofDs=);
DATA &ofDs._subset;
MERGE &ofDs(in=in1) finderFileDs (in=in2);
BY id;
IF in1 and in2;
RUN;
%MEND;
%getSubset(ofDs=patientDs );
%getSubset(ofDs=consultDs );
%getSubset(ofDs=hospStayDs);
%getSubset(ofDs=eventsDs );
%getSubset(ofDs=drugsDs );
Still got cookies!
Still list elements are dispersed.
10
Ex. with %wordLoop
%MACRO getSubset( );
DATA &word._subset;
MERGE &word.(in=in1) finderFileDs(in=in2);
BY id;
IF in1 and in2;
RUN;
%MEND;
%LET ds=patientDs consultDs hospStayDs eventsDs
drugsDs;
%wordLoop(wordList=&ds,contentMacro=getSubset( ));
Oops! What about sort order?
11
Again with sort
%MACRO getSubset();
proc sort DATA=&word; BY id; RUN;
DATA &word._subset;
MERGE &word.(in=in1) finderFileDs(in=in2);
BY id;
IF in1 and in2;
RUN;
%MEND;
%LET ds=patientDs consultDs hospStayDs eventsDs
drugsDs;
%wordLoop(wordList=&ds,contentMacro=getSubset( ));
SQL better?
12
Again with SQL
%MACRO getSubset();
PROC sql;
create table &word._subset as
select * from &word, finderFileDs
where &word..id = finderFileDs.id;
QUIT;
%MEND;
%LET ds=patientDs consultDs hospStayDs eventsDs drugsDs;
%wordLoop(wordList=&ds,contentMacro=getSubset( ));
Change localized!
13
%wordLoop code
%MACRO wordLoop(wordList=, contentMacro=);
%LOCAL word cnt;
%LET cnt=0;
%DO %WHILE(1 eq 1);
%LET cnt = %eval(&cnt+1);
%LET word= %scan(&wordList, &cnt, %str( ));
%IF &word= %THEN %RETURN;
%&contentMacro;
%END;
%MEND wordLoop;
ContentMacro must not %LOCAL word!
14
Example 2 Code
Recode 99 to “.” for selected variables
 5 variables need to be recoded
 3 variables might have valid 99s
 CCC occurs within a DATA step

15
Ex. 2 Cookie-Cutter Code
DATA data99sFixed;
SETdataWith99sDs;
IF eyeColor eq 99 THEN eyeColor = .;
IF hairColor eq 99 THEN hairColor = .;
IF bloodtype eq 99 THEN bloodtype = .;
IF prevCardiac eq 99 THEN prevCardiac = .;
IF prevCancer eq 99 THEN prevCancer = .;
RUN;
16
Ex. 2 with Array Solution
%LET varsWith99 = eyeColor hairColor bloodtype
prevCardiac prevCancer;
DATA data99sFixedDs;
SET dataWith99sDs;
ARRAY vars99arr{*} &varsWith99;
DO i=1 to dim(vars99arr);
IF vars99arr(i) eq 99 THEN vars99arr(i) = .;
END;
DROP i;
RUN;
This works but so does …
17
Ex. 2 with %wordLoop
%LET varsWith99 = eyeColor hairColor bloodtype
prevCardiac prevCancer;
%MACRO cnvt99s();
IF &word eq 99 THEN &word= .;
%MEND;
DATA data99sFixed;
SETdataWith99sDs;
%wordLoop(wordList=&varsWith99,
contentMacro=cnvt99s());
RUN;
18
Misuses of %wordLoop
Avoid use with datasets representing
partitions of DATA (e.g. sites)
 Combine and processBY site, instead
 Avoid use with procs whenBY or CLASS
can be used (e.g. PROC MEANS)

19
Take Aways
Avoid cookie-cutter-code!
 %wordLoop() can help you do this
 SAS macros allow you to adapt the SAS
language to your purposes.

[email protected]
20