BookmarkSubscribeRSS Feed
Jarot741
Calcite | Level 5

Hi all,

 

I need help with the following:

 

PRE-Matching

My treatment cohort is 427 and the control 4079

 

POST-Matching

My treatment cohort is 1281 and the control 1281

 

I am wanting to do a 3:1 match, and not sure why I ended up with the last numbers.

I am using this macro by Marcelo Coca Perraillon Paper 185-2007:

 

%macro PSMatching(datatreatment=, datacontrol=,
method=, numberofcontrols=, caliper=,
 replacement=, out=);

/* Create copies of the treated units if N > 1 */;
 data _Treatment0(drop= i);
  set &datatreatment;
  do i= 1 to &numberofcontrols;
  RandomNumber= ranuni(12345);
output;
end;
run;

/* Randomly sort both datasets */
proc sort data= _Treatment0 out= _Treatment(drop= RandomNumber);
by RandomNumber;
run;
data _Control0;
set &datacontrol;
RandomNumber= ranuni(45678);
run;
proc sort data= _Control0 out= _Control(drop= RandomNumber);
by RandomNumber;
run;

 data Matched(keep = IdSelectedControl PScoreControl MatchedToTreatID PScoreTreat);
  length pscoreC 8;
  length idC 8;
/* Load Control dataset into the hash object */
  if _N_= 1 then do;
declare hash h(dataset: "_Control", ordered: 'no');
declare hiter iter('h');
h.defineKey('idC');
h.defineData('pscoreC', 'idC');
h.defineDone();
call missing(idC, pscoreC);
end;
/* Open the treatment */
set _Treatment;
%if %upcase(&method) ~= RADIUS %then %do;
retain BestDistance 99;
%end;
/* Iterate over the hash */
rc= iter.first();
if (rc=0) then BestDistance= 99;
do while (rc = 0);


/* Caliper */
%if %upcase(&method) = CALIPER %then %do;
if (pscoreT - &caliper) <= pscoreC <= (pscoreT + &caliper) then do;
ScoreDistance = abs(pscoreT - pscoreC);
if ScoreDistance < BestDistance then do;
BestDistance = ScoreDistance;
IdSelectedControl = idC;
PScoreControl =  pscoreC;
MatchedToTreatID = idT;
PScoreTreat = pscoreT;
end;
end;
%end;



/* NN */
%if %upcase(&method) = NN %then %do;
ScoreDistance = abs(pscoreT - pscoreC);
if ScoreDistance < BestDistance then do;
BestDistance = ScoreDistance;
IdSelectedControl = idC;
PScoreControl =  pscoreC;
MatchedToTreatID = idT;
PScoreTreat = pscoreT;
end;
%end;

%if %upcase(&method) = NN or %upcase(&method) = CALIPER %then %do;
rc = iter.next();
/* Output the best control and remove it */
if (rc ~= 0) and BestDistance ~=99 then do;
output;
%if %upcase(&replacement) = NO %then %do;
rc1 = h.remove(key: IdSelectedControl);
%end;
end;
%end;
/* Radius */
%if %upcase(&method) = RADIUS %then %do;
if (pscoreT - &caliper) <= pscoreC <= (pscoreT + &caliper) then do;
IdSelectedControl = idC;
PScoreControl =  pscoreC;
MatchedToTreatID = idT;
PScoreTreat = pscoreT;
output;
end;
rc = iter.next();
%end;
end;
run;
/* Delete temporary tables. Quote for debugging */
proc datasets;
delete _ : gennum=all);

run;
 data &out;
   set Matched;
 run;
%mend PSMatching;

 

And I am invoking it :

 

%PSMatching(datatreatment=PNET._MIPD_YES, datacontrol=PNET._MIPD_NO,
method=NN, numberofcontrols=3, caliper=0.1, replacement=NO, out=MATCHES); RUN;

 

Any ideas?

Thanks,

J

1 REPLY 1
Reeza
Super User

You stared with: N=427, so if you want a 1:3 match, that becomes 1281 records. 

 

Each treatment is matched with 3 controls. If you have a unique variable that identifies your rows, check your data and you should find that you have duplicates of your case data, triplicates and each control should be unique. 

 

EDIT:

Please include code in a code block in the future and if you're using SAS 9.4 TSM5+ there is a PROC PSMATCH now available to do these types of matching as well. 

 

Source of macro: http://www2.sas.com/proceedings/forum2007/185-2007.pdf

 


@Jarot741 wrote:

Hi all,

 

I need help with the following:

 

PRE-Matching

My treatment cohort is 427 and the control 4079

 

POST-Matching

My treatment cohort is 1281 and the control 1281

 

I am wanting to do a 3:1 match, and not sure why I ended up with the last numbers.

I am using this macro by Marcelo Coca Perraillon Paper 185-2007:

 

 

%macro PSMatching(datatreatment=, datacontrol=, method=, numberofcontrols=, 
        caliper=, replacement=, out=);
    /* Create copies of the treated units if N > 1 */;

    data _Treatment0(drop=i);
        set &datatreatment;

        do i=1 to &numberofcontrols;
            RandomNumber=ranuni(12345);
            output;
        end;
    run;

    /* Randomly sort both datasets */
    proc sort data=_Treatment0 out=_Treatment(drop=RandomNumber);
        by RandomNumber;
    run;

    data _Control0;
        set &datacontrol;
        RandomNumber=ranuni(45678);
    run;

    proc sort data=_Control0 out=_Control(drop=RandomNumber);
        by RandomNumber;
    run;

    data Matched(keep=IdSelectedControl PScoreControl MatchedToTreatID 
            PScoreTreat);
        length pscoreC 8;
        length idC 8;

        /* Load Control dataset into the hash object */
        if _N_=1 then
            do;
                declare hash h(dataset: "_Control", ordered: 'no');
                declare hiter iter('h');
                h.defineKey('idC');
                h.defineData('pscoreC', 'idC');
                h.defineDone();
                call missing(idC, pscoreC);
            end;

        /* Open the treatment */
        set _Treatment;

        %if %upcase(&method) ~=RADIUS %then
            %do;
                retain BestDistance 99;
            %end;

        /* Iterate over the hash */
        rc=iter.first();

        if (rc=0) then
            BestDistance=99;

        do while (rc=0);

            /* Caliper */

            %if %upcase(&method)=CALIPER %then
                %do;

                    if (pscoreT - &caliper) <=pscoreC <=(pscoreT + &caliper) then
                        do;
                            ScoreDistance=abs(pscoreT - pscoreC);

                            if ScoreDistance < BestDistance then
                                do;
                                    BestDistance=ScoreDistance;
                                    IdSelectedControl=idC;
                                    PScoreControl=pscoreC;
                                    MatchedToTreatID=idT;
                                    PScoreTreat=pscoreT;
                                end;
                        end;
                %end;

            /* NN */

            %if %upcase(&method)=NN %then
                %do;
                    ScoreDistance=abs(pscoreT - pscoreC);

                    if ScoreDistance < BestDistance then
                        do;
                            BestDistance=ScoreDistance;
                            IdSelectedControl=idC;
                            PScoreControl=pscoreC;
                            MatchedToTreatID=idT;
                            PScoreTreat=pscoreT;
                        end;
                %end;

            %if %upcase(&method)=NN or %upcase(&method)=CALIPER %then
                %do;
                    rc=iter.next();

                    /* Output the best control and remove it */
                    if (rc ~=0) and BestDistance ~=99 then
                        do;
                            output;

                            %if %upcase(&replacement)=NO %then
                                %do;
                                    rc1=h.remove(key: IdSelectedControl);
                                %end;
                        end;
                %end;

            /* Radius */

            %if %upcase(&method)=RADIUS %then
                %do;

                    if (pscoreT - &caliper) <=pscoreC <=(pscoreT + &caliper) then
                        do;
                            IdSelectedControl=idC;
                            PScoreControl=pscoreC;
                            MatchedToTreatID=idT;
                            PScoreTreat=pscoreT;
                            output;
                        end;
                    rc=iter.next();
                %end;
        end;
    run;

    /* Delete temporary tables. Quote for debugging */
    proc datasets;
        delete _ : gennum=all);
        run;

    data &out;
        set Matched;
    run;

%mend PSMatching;

*And I am invoking it;
 
%PSMatching(datatreatment=PNET._MIPD_YES, datacontrol=PNET._MIPD_NO, method=NN, 
    numberofcontrols=3, caliper=0.1, replacement=NO, out=MATCHES);
RUN;

 

Any ideas?

Thanks,

J


 

 

sas-innovate-white.png

Missed SAS Innovate in Orlando?

Catch the best of SAS Innovate 2025 — anytime, anywhere. Stream powerful keynotes, real-world demos, and game-changing insights from the world’s leading data and AI minds.

 

Register now

Mastering the WHERE Clause in PROC SQL

SAS' Charu Shankar shares her PROC SQL expertise by showing you how to master the WHERE clause using real winter weather data.

Find more tutorials on the SAS Users YouTube channel.

Discussion stats
  • 1 reply
  • 1559 views
  • 0 likes
  • 2 in conversation