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

That will most likely need a macro.

It looks like you have a single iteration built, so I assume you're not familiar with macro coding and want someone to write the macro for you?

SWEETSAS
Obsidian | Level 7

Yes. I am having a hard time writing the macro that can do this iteratively.

Tom
Super User Tom
Super User

Try this macro.


%macro match

(cases=ref       /* List of records to use as CASES */

,controls=main   /* List of records to use as CONTROLS */

,id=id           /* ID variable in CONTROLS */

,varlist=x y     /* Variables to use in distance calculations */

,out=out         /* Output dataset */

,with_replacement=0  /* Select with replacement? (0/1) */

);

%local i n rename remove ;

%* Generate RENAME list for &VARLIST varaibles ;

%do i=1 %to %sysfunc(countw(&varlist));

  %let rename=&rename %scan(&varlist,&i)=match_%scan(&varlist,&i);

%end;

* Get count of number of cases ;

data _null_;

  if eof then call symputx('n',_n_ -1);

  set &cases end=eof;

run;

* Use all CONTROL records to start with ;

data distance;

  set &controls;

  keep &id &varlist ;

run;

%if %sysfunc(exist(&out)) or %sysfunc(exist(&out,view)) %then %do;

* Remove existing output dataset ;

proc delete data=&out; run;

%end;

%* Set REMOVE to missing value to that all controls used on first pass;

%let remove=.;

%do i=1 %to &n ;

* Calculate distance from next CASES, exclude previosly used CONTROL ;

proc fastclus maxc=1 replace=none maxiter=0 noprint

  data=distance(where=((&id ^= &remove)))

  seed=&cases (firstobs=&i obs=&i )

  out=distance ;

;

  var &varlist;

run;

* Sort to find closest ;

proc sort; by distance ; run;

* Generate next record ;

* Set REMOVE to eliminate this case ;

data next ;

  set &cases (firstobs=&i obs=&i);

  set distance(obs=1 keep=&id &varlist distance rename=(&id=match_&id &rename));

  if not &with_replacement then call symputx('remove',match_&id);

run;

* Add to output dataset ;

proc append base=&out data=next force;

run;

%end;

%mend match;

data main;

input id x y;

datalines;

1 0.5 0.3

2 0.7  1.3

3 2.0  0.8

4 0.6 0.45

5 .25   .4

;

data ref;

input id x y;

datalines;

1 0.6  1.2

2 0.5  0.7

3 -0.3  1.5

;

options mprint ;

%match() ;

proc print;

run;

%match(with_replacement=1) ;

proc print;

run;

Without Replacement
Obsidxymatch_idmatch_xmatch_yDISTANCE
110.6120.71.30.14142
220.5140.60.450.26926
33-0.3250.250.41.22984
With Replacement
Obsidxymatch_idmatch_xmatch_yDISTANCE
110.6120.71.30.14142
220.5140.60.450.26926
33-0.3220.71.31.0198
SWEETSAS
Obsidian | Level 7

Tom.

This is I-N-C-R-E-D-I-B-L-E!!!!!!!You made my Christmas! This a best Santa gift ever.

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
  • 18 replies
  • 4227 views
  • 3 likes
  • 4 in conversation