Thank you SO much for your help! Your suggestions worked! I converted missing values in my array variables to 0 (which I think was one of my biggest problems!), got rid of the macro and moved it into my main code, and I also realized I needed to add all variables I reference in the code into the 'definedata' step of my hash table. In case there are others struggling with a similar problem, here's my full code below: *prepare datasets*; data controls (keep=control_id control_age control_gender a200701-a201412 b200701-b201412 d200701-d201412 control_rand registry2007-registry2015); set control_enroll_1; control_age=year(birth_dt); control_gender=input(m_sex, best12.); *convert to numeric*; control_id=patient_id; control_rand=ranuni(0); run; data controls_1; set controls; *convert missing to 0*; array _a a200701--a201412; do i=1 to dim(_a); if _a[i]=. then _a[i]=0; end; array _b b200701--b201412; do i=1 to dim(_b); if _b[i]=. then _b[i]=0; end; array _d d200701--d201412; do i=1 to dim(_d); if _d[i]=. then _d[i]=0; end; run; data cases (keep=case_id cancer_dxdt case_age case_gender case_rand count reg1); set exposed; case_age=year(birth_dt); case_gender=input(M_sex, best12.); *convert to numeric*; case_id=patient_id; case_rand=ranuni(0); *for scramble the order of cases; count=0; run; *for recording number of controls matched; data cases_1; set cases; count1= input(count, best12.); *convert to numeric bc SAS is being DUMB*; yr_b4=cancer_dxdt-365; format yr_b4 date7.; run; data cases_2; set cases_1; yrb4_yr = year(yr_b4); yrb4_mo = month(yr_b4); run; *"case_id","control_id","case_age","control_age","cancer_dxdt","control_gender","case_gender"*; * the main data step; %let ratio=2; data _null_; if _n_=1 then do; set cases_2(obs=1); *make the variables in Cases data set available in the PDV; *put the cases in a hash table; declare hash cases(dataset:"cases_2",hashexp:8,ordered:"y"); cases.definekey("case_rand","case_id"); cases.definedata("case_rand","case_id","count1","case_age","case_gender","cancer_dxdt","reg1","yrb4_yr","yrb4_mo"); cases.definedone(); declare hiter hi_cases('cases'); * declare a hash table iterator object; declare hash matches(); *declare a hash table for matched cases and controls; matches.definekey("case_id","control_id"); matches.definedata("case_id","control_id","case_age","control_age","cancer_dxdt","control_gender","case_gender","reg1","REGISTRY2007","REGISTRY2008","REGISTRY2009","REGISTRY2010", "REGISTRY2011","REGISTRY2012","REGISTRY2013","REGISTRY2014","yrb4_yr","yrb4_mo", "a200701","a200702","a200703","a200704","a200705","a200706","a200707","a200708","a200709","a200710","a200711","a200712", "a200801","a200802","a200803","a200804","a200805","a200806","a200807","a200808","a200809","a200810","a200811","a200812", "a200901","a200902","a200903","a200904","a200905","a200906","a200907","a200908","a200909","a200910","a200911","a200912", "a201001","a201002","a201003","a201004","a201005","a201006","a201007","a201008","a201009","a201010","a201011","a201012", "a201101","a201102","a201103","a201104","a201105","a201106","a201107","a201108","a201109","a201110","a201111","a201112", "a201201","a201202","a201203","a201204","a201205","a201206","a201207","a201208","a201209","a201210","a201211","a201212", "a201301","a201302","a201303","a201304","a201305","a201306","a201307","a201308","a201309","a201310","a201311","a201312", "a201401","a201402","a201403","a201404","a201405","a201406","a201407","a201408","a201409","a201410","a201411","a201412", "b200701","b200702","b200703","b200704","b200705","b200706","b200707","b200708","b200709","b200710","b200711","b200712", "b200801","b200802","b200803","b200804","b200805","b200806","b200807","b200808","b200809","b200810","b200811","b200812", "b200901","b200902","b200903","b200904","b200905","b200906","b200907","b200908","b200909","b200910","b200911","b200912", "b201001","b201002","b201003","b201004","b201005","b201006","b201007","b201008","b201009","b201010","b201011","b201012", "b201101","b201102","b201103","b201104","b201105","b201106","b201107","b201108","b201109","b201110","b201111","b201112", "b201201","b201202","b201203","b201204","b201205","b201206","b201207","b201208","b201209","b201210","b201211","b201212", "b201301","b201302","b201303","b201304","b201305","b201306","b201307","b201308","b201309","b201310","b201311","b201312", "b201401","b201402","b201403","b201404","b201405","b201406","b201407","b201408","b201409","b201410","b201411","b201412", "d200701","d200702","d200703","d200704","d200705","d200706","d200707","d200708","d200709","d200710","d200711","d200712", "d200801","d200802","d200803","d200804","d200805","d200806","d200807","d200808","d200809","d200810","d200811","d200812", "d200901","d200902","d200903","d200904","d200905","d200906","d200907","d200908","d200909","d200910","d200911","d200912", "d201001","d201002","d201003","d201004","d201005","d201006","d201007","d201008","d201009","d201010","d201011","d201012", "d201101","d201102","d201103","d201104","d201105","d201106","d201107","d201108","d201109","d201110","d201111","d201112", "d201201","d201202","d201203","d201204","d201205","d201206","d201207","d201208","d201209","d201210","d201211","d201212", "d201301","d201302","d201303","d201304","d201305","d201306","d201307","d201308","d201309","d201310","d201311","d201312", "d201401","d201402","d201403","d201404","d201405","d201406","d201407","d201408","d201409","d201410","d201411","d201412"); matches.definedone(); *declare a hash table for recording matched controls; control_id_hash=case_id; declare hash m_control(); m_control.definekey("control_id_hash"); m_control.definedone(); m_control.clear(); end; set controls_1 end=eof; control_id_hash=control_id; *get current control_id for searching; if (m_control.find() ne 0) then do; *not matched to a case yet; rc=hi_cases.first(); *search cases table using hash iterator object; do while(rc=0); eligibility=0; array _a(2007:2014, 12) a200701--a201412; array _b(2007:2014, 12) b200701--b201412; array _d(2007:2014, 12) d200701--d201412; if (_a(yrb4_yr, yrb4_mo)>=12) and (_b(yrb4_yr, yrb4_mo)>=12) and (_d(yrb4_yr, yrb4_mo)>=12) then _enroll_pre=1; else _enroll_pre=0; if abs(case_age-control_age)<= 2 and case_gender=control_gender and _enroll_pre=1 and (REG1=REGISTRY2007 or REG1=REGISTRY2008 or REG1=REGISTRY2009 or REG1=REGISTRY2010 or REG1=REGISTRY2011 or REG1=REGISTRY2012 or REG1=REGISTRY2013) then eligibility=1; if (count1<&ratio. and eligibility=1) then do; count1+1; cases.replace(); matches.add(); m_control.add(); leave; end; rc=hi_cases.next(); end; end; *check if all the cases have matches (ie, count=&ratio.); done=1; rc=hi_cases.first(); do while(rc=0); if count1<&ratio. then do; done=0; leave; end; rc=hi_cases.next(); end; *if all the cases are matched or run out of controls, output the resulting data sets; if (done or eof) then do; matches.output(dataset:"matches_round1"); cases.output(dataset:"matched_cases_round1"); m_control.output(dataset:"matched_controls_round1"); stop; end; run;
... View more