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