<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic De-duplicating controls in matched case/control study in Mathematical Optimization, Discrete-Event Simulation, and OR</title>
    <link>https://communities.sas.com/t5/Mathematical-Optimization/De-duplicating-controls-in-matched-case-control-study/m-p/972468#M4341</link>
    <description>&lt;P&gt;Hi,&lt;/P&gt;&lt;P&gt;I used SAS a code published here to match cases and controls using the "Linear Assignment - graph directed method" (published in 2020) - please see the code attached below.&amp;nbsp;&lt;/P&gt;&lt;P&gt;This code worked perfectly with my dataset and I could select controls on 1:5 with no duplicate controls.&amp;nbsp;&lt;/P&gt;&lt;P&gt;However, a researcher I worked with checked the code and mentioned that there is a possibility to select the controls "non-randomly" from this method.&amp;nbsp;&lt;/P&gt;&lt;P&gt;So, I want to know if this method selects the controls randomly or not.&amp;nbsp;&amp;nbsp;Could you please check the code and confirm to me if the controls are randomly selected in this method as random selection of controls is encouraged in this project?&amp;nbsp;&lt;/P&gt;&lt;P&gt;Thank you so much.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;The Code:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;data have;&lt;/P&gt;&lt;P&gt;input case_id&amp;nbsp; control_id;&lt;/P&gt;&lt;P&gt;datalines;&lt;/P&gt;&lt;P&gt;&amp;nbsp; 1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 10&lt;/P&gt;&lt;P&gt;&amp;nbsp; 1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 125&lt;/P&gt;&lt;P&gt;&amp;nbsp; 1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1850&lt;/P&gt;&lt;P&gt;&amp;nbsp; 1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 928&lt;/P&gt;&lt;P&gt;&amp;nbsp; 3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 125&lt;/P&gt;&lt;P&gt;&amp;nbsp; 3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 8&lt;/P&gt;&lt;P&gt;&amp;nbsp; 3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1276&lt;/P&gt;&lt;P&gt;&amp;nbsp; 3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1011&lt;/P&gt;&lt;P&gt;&amp;nbsp; 3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 10&lt;/P&gt;&lt;P&gt;&amp;nbsp; 4&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 10&lt;/P&gt;&lt;P&gt;&amp;nbsp; 4&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1011&lt;/P&gt;&lt;P&gt;;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;data links1;&lt;/P&gt;&lt;P&gt;set have;&lt;/P&gt;&lt;P&gt;rename case_id=from control_id=to;&lt;/P&gt;&lt;P&gt;weight = 1;&lt;/P&gt;&lt;P&gt;run;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;proc optnet data_links=links1 GRAPH_DIRECTION=DIRECTED;&lt;/P&gt;&lt;P&gt;linear_assignment out=want1;&lt;/P&gt;&lt;P&gt;run;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;proc print data=want1; run;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;proc sql;&lt;/P&gt;&lt;P&gt;create table links2 as&lt;/P&gt;&lt;P&gt;select * from links1&lt;/P&gt;&lt;P&gt;where to not in (select to from want1);&lt;/P&gt;&lt;P&gt;quit;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;proc optnet data_links=links2 GRAPH_DIRECTION=DIRECTED;&lt;/P&gt;&lt;P&gt;linear_assignment out=want2;&lt;/P&gt;&lt;P&gt;run;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;proc print data=want2; run;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;proc sql;&lt;/P&gt;&lt;P&gt;create table links3 as&lt;/P&gt;&lt;P&gt;select * from links2&lt;/P&gt;&lt;P&gt;where to not in (select to from want2);&lt;/P&gt;&lt;P&gt;quit;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;proc optnet data_links=links3 GRAPH_DIRECTION=DIRECTED;&lt;/P&gt;&lt;P&gt;linear_assignment out=want3;&lt;/P&gt;&lt;P&gt;run;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;proc print data=want3; run;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;data want;&lt;/P&gt;&lt;P&gt;set want1 want2 want3;&lt;/P&gt;&lt;P&gt;rename from=case_id to=control_id;&lt;/P&gt;&lt;P&gt;drop weight;&lt;/P&gt;&lt;P&gt;run;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;proc sort data=want; by case_id control_id; run;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;proc print data=want noobs; run;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
    <pubDate>Mon, 11 Aug 2025 23:48:12 GMT</pubDate>
    <dc:creator>shanj</dc:creator>
    <dc:date>2025-08-11T23:48:12Z</dc:date>
    <item>
      <title>De-duplicating controls in matched case/control study</title>
      <link>https://communities.sas.com/t5/Mathematical-Optimization/De-duplicating-controls-in-matched-case-control-study/m-p/972468#M4341</link>
      <description>&lt;P&gt;Hi,&lt;/P&gt;&lt;P&gt;I used SAS a code published here to match cases and controls using the "Linear Assignment - graph directed method" (published in 2020) - please see the code attached below.&amp;nbsp;&lt;/P&gt;&lt;P&gt;This code worked perfectly with my dataset and I could select controls on 1:5 with no duplicate controls.&amp;nbsp;&lt;/P&gt;&lt;P&gt;However, a researcher I worked with checked the code and mentioned that there is a possibility to select the controls "non-randomly" from this method.&amp;nbsp;&lt;/P&gt;&lt;P&gt;So, I want to know if this method selects the controls randomly or not.&amp;nbsp;&amp;nbsp;Could you please check the code and confirm to me if the controls are randomly selected in this method as random selection of controls is encouraged in this project?&amp;nbsp;&lt;/P&gt;&lt;P&gt;Thank you so much.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;The Code:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;data have;&lt;/P&gt;&lt;P&gt;input case_id&amp;nbsp; control_id;&lt;/P&gt;&lt;P&gt;datalines;&lt;/P&gt;&lt;P&gt;&amp;nbsp; 1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 10&lt;/P&gt;&lt;P&gt;&amp;nbsp; 1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 125&lt;/P&gt;&lt;P&gt;&amp;nbsp; 1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1850&lt;/P&gt;&lt;P&gt;&amp;nbsp; 1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 928&lt;/P&gt;&lt;P&gt;&amp;nbsp; 3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 125&lt;/P&gt;&lt;P&gt;&amp;nbsp; 3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 8&lt;/P&gt;&lt;P&gt;&amp;nbsp; 3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1276&lt;/P&gt;&lt;P&gt;&amp;nbsp; 3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1011&lt;/P&gt;&lt;P&gt;&amp;nbsp; 3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 10&lt;/P&gt;&lt;P&gt;&amp;nbsp; 4&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 10&lt;/P&gt;&lt;P&gt;&amp;nbsp; 4&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1011&lt;/P&gt;&lt;P&gt;;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;data links1;&lt;/P&gt;&lt;P&gt;set have;&lt;/P&gt;&lt;P&gt;rename case_id=from control_id=to;&lt;/P&gt;&lt;P&gt;weight = 1;&lt;/P&gt;&lt;P&gt;run;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;proc optnet data_links=links1 GRAPH_DIRECTION=DIRECTED;&lt;/P&gt;&lt;P&gt;linear_assignment out=want1;&lt;/P&gt;&lt;P&gt;run;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;proc print data=want1; run;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;proc sql;&lt;/P&gt;&lt;P&gt;create table links2 as&lt;/P&gt;&lt;P&gt;select * from links1&lt;/P&gt;&lt;P&gt;where to not in (select to from want1);&lt;/P&gt;&lt;P&gt;quit;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;proc optnet data_links=links2 GRAPH_DIRECTION=DIRECTED;&lt;/P&gt;&lt;P&gt;linear_assignment out=want2;&lt;/P&gt;&lt;P&gt;run;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;proc print data=want2; run;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;proc sql;&lt;/P&gt;&lt;P&gt;create table links3 as&lt;/P&gt;&lt;P&gt;select * from links2&lt;/P&gt;&lt;P&gt;where to not in (select to from want2);&lt;/P&gt;&lt;P&gt;quit;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;proc optnet data_links=links3 GRAPH_DIRECTION=DIRECTED;&lt;/P&gt;&lt;P&gt;linear_assignment out=want3;&lt;/P&gt;&lt;P&gt;run;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;proc print data=want3; run;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;data want;&lt;/P&gt;&lt;P&gt;set want1 want2 want3;&lt;/P&gt;&lt;P&gt;rename from=case_id to=control_id;&lt;/P&gt;&lt;P&gt;drop weight;&lt;/P&gt;&lt;P&gt;run;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;proc sort data=want; by case_id control_id; run;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;proc print data=want noobs; run;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Mon, 11 Aug 2025 23:48:12 GMT</pubDate>
      <guid>https://communities.sas.com/t5/Mathematical-Optimization/De-duplicating-controls-in-matched-case-control-study/m-p/972468#M4341</guid>
      <dc:creator>shanj</dc:creator>
      <dc:date>2025-08-11T23:48:12Z</dc:date>
    </item>
    <item>
      <title>Re: De-duplicating controls in matched case/control study</title>
      <link>https://communities.sas.com/t5/Mathematical-Optimization/De-duplicating-controls-in-matched-case-control-study/m-p/972475#M4342</link>
      <description>I am definitely not familiar with this 'graph directed' method.  Not really clear what variables you're matching on here.  Re: randomness, how did you create the 'have' dataset in the first place?  Were the controls randomly sorted and then you just created a cartesian product of the cases and controls?</description>
      <pubDate>Tue, 12 Aug 2025 01:59:01 GMT</pubDate>
      <guid>https://communities.sas.com/t5/Mathematical-Optimization/De-duplicating-controls-in-matched-case-control-study/m-p/972475#M4342</guid>
      <dc:creator>quickbluefish</dc:creator>
      <dc:date>2025-08-12T01:59:01Z</dc:date>
    </item>
    <item>
      <title>Re: De-duplicating controls in matched case/control study</title>
      <link>https://communities.sas.com/t5/Mathematical-Optimization/De-duplicating-controls-in-matched-case-control-study/m-p/972478#M4343</link>
      <description>&lt;P&gt;Hi,&amp;nbsp;&lt;/P&gt;&lt;P&gt;Thank you for your reply. This is the link to the original post -&amp;nbsp;&lt;A href="https://communities.sas.com/t5/SAS-Programming/De-duplicating-controls-in-matched-case-control/td-p/648708" target="_blank"&gt;https://communities.sas.com/t5/SAS-Programming/De-duplicating-controls-in-matched-case-control/td-p/648708&lt;/A&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I created the 'have' dataset by matching on two variables - age and ethnicity.&lt;/P&gt;&lt;P&gt;I did not randomly select the controls as the dataset to select controls in this study was very small.&amp;nbsp;&lt;/P&gt;&lt;P&gt;Your help is much appreciated.&lt;/P&gt;&lt;P&gt;Thanks.&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Tue, 12 Aug 2025 07:32:19 GMT</pubDate>
      <guid>https://communities.sas.com/t5/Mathematical-Optimization/De-duplicating-controls-in-matched-case-control-study/m-p/972478#M4343</guid>
      <dc:creator>shanj</dc:creator>
      <dc:date>2025-08-12T07:32:19Z</dc:date>
    </item>
    <item>
      <title>Re: De-duplicating controls in matched case/control study</title>
      <link>https://communities.sas.com/t5/Mathematical-Optimization/De-duplicating-controls-in-matched-case-control-study/m-p/972483#M4344</link>
      <description>&lt;P&gt;Assuming I understood your question.&lt;/P&gt;
&lt;P&gt;Try this one:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data have;
input case_id  control_id;
datalines;
  1         10
  1        125
  1     1850
  1       928
  3       125
  3          8
  3     1276
  3      1011
  3         10
  4         10
  4      1011
;


%let n=3;  *each case_id has 3 control_id at most;

data have2;
 set have;
 call streaminit(1234);
 random=rand('uniform');
run;
proc sort data=have2;
by case_id random;
run;
data want;
if _n_=1 then do;
 if 0 then set have;
 declare hash h();
 h.definekey('control_id');
 h.definedone();
end;
set have2;
by case_id;
if first.case_id then count=0;
if h.check() ne 0 and count&amp;lt;&amp;amp;n. then do;
  count+1;
  h.add();
  output;
end;
run;&lt;/CODE&gt;&lt;/PRE&gt;</description>
      <pubDate>Tue, 12 Aug 2025 08:52:35 GMT</pubDate>
      <guid>https://communities.sas.com/t5/Mathematical-Optimization/De-duplicating-controls-in-matched-case-control-study/m-p/972483#M4344</guid>
      <dc:creator>Ksharp</dc:creator>
      <dc:date>2025-08-12T08:52:35Z</dc:date>
    </item>
    <item>
      <title>Re: De-duplicating controls in matched case/control study</title>
      <link>https://communities.sas.com/t5/Mathematical-Optimization/De-duplicating-controls-in-matched-case-control-study/m-p/972510#M4345</link>
      <description>&lt;P&gt;You might be interested in PROC PSMATCH, which uses a linear assignment solver under the hood for optimal matching:&lt;/P&gt;
&lt;P&gt;&lt;A href="https://go.documentation.sas.com/doc/en/pgmsascdc/v_065/statug/statug_psmatch_toc.htm" target="_blank"&gt;https://go.documentation.sas.com/doc/en/pgmsascdc/v_065/statug/statug_psmatch_toc.htm&lt;/A&gt;&lt;/P&gt;</description>
      <pubDate>Tue, 12 Aug 2025 16:44:00 GMT</pubDate>
      <guid>https://communities.sas.com/t5/Mathematical-Optimization/De-duplicating-controls-in-matched-case-control-study/m-p/972510#M4345</guid>
      <dc:creator>RobPratt</dc:creator>
      <dc:date>2025-08-12T16:44:00Z</dc:date>
    </item>
  </channel>
</rss>

