Sas 有人喝咖啡吗?
我在C#尝试过这个,但没有太大成功。所以我现在在SAS尝试。使用EG会话和我的SAS代码,我们处理SASHELP.CLASS中的学生列表。 这些人希望彼此了解,每月随机配对,一起去喝咖啡约会 规则: 每月生成一个随机咖啡日期列表; 我将每个月的配对存储到一个历史数据集中,并每月追加一次 一个人不能在6个月内与同一个人一起喝咖啡。因此,我们为历史目的保留了一个单独的数据集,其中包含3个变量: 最后日期,InviterID,InvitedID 我们根据历史列表检查每个配对,我们仅将最近6个月的数据加载到临时数据集中进行检查 如果未找到最近的匹配对,则将新的匹配对添加到新的配对数据集中,并从原始参与者数据集中删除2个名称(行),直到该数据集中的行数少于2行。(一个人不能与另一个人配对) 不幸的是,此列表中有19人,因此在我们添加新参与者之前,其中一人将被排除在外。有人想加入我们的咖啡俱乐部吗?:-) 因此,我首先从数据集中派生和ID(n),并且只保留名称Sas 有人喝咖啡吗?,sas,Sas,我在C#尝试过这个,但没有太大成功。所以我现在在SAS尝试。使用EG会话和我的SAS代码,我们处理SASHELP.CLASS中的学生列表。 这些人希望彼此了解,每月随机配对,一起去喝咖啡约会 规则: 每月生成一个随机咖啡日期列表; 我将每个月的配对存储到一个历史数据集中,并每月追加一次 一个人不能在6个月内与同一个人一起喝咖啡。因此,我们为历史目的保留了一个单独的数据集,其中包含3个变量: 最后日期,InviterID,InvitedID 我们根据历史列表检查每个配对,我们仅将最近6个月的数据加
Data Participants(Keep=ID Name);
FORMAT ID 8.;
set SASHelp.class;
ID=_n_;
run;
这19个人将是我在咖啡俱乐部的参与者
我或多或少遵循这样的思路:
data _null_;
randvar = ceil(rand('UNIFORM') * 100000);
call symput('RANDSEED', randvar);
run;
data CR.names2(keep=MEMID randid);
set CR.MasterNames;
randid = rand('UNIFORM');
run;
proc sort data=CR.names2 ; by randid; run;
data CR.pairs(keep=pairgrp MEMID);
set CR.names2 nobs=num_peeps;
pairgrp+1;
if pairgrp > floor(num_peeps/2) then pairgrp=1;
run;
proc sort data=CR.pairs; by pairgrp;run;
proc transpose data=CR.pairs
out=CR.pairs2 (drop=_NAME_);
var memid;
by pairgrp;
run;
Data CR.Pairs3;
set CR.pairs2;
rename COL1=InviterID COL2=InvitedID;
run;
但我被卡住了:-(
其余的我需要帮助请
以前有人成功地进行过这种随机配对吗?我在这里抓救命稻草。。。
非常感谢您的帮助。
Len这是我的想法。这远远不够有效。尤其是当NOB变得越来越大时,因为涉及到笛卡尔积。在这种情况下,我还通过添加另一行来欺骗奇数
data Participants(Keep=ID Name) ;
set SASHelp.class nobs = num_peeps ;
ID=_n_ ;
output ;
if _n_ = 1 and mod(num_peeps,2) then do ; /* get even number of members: empty ID to pair with last participant*/
name = 'empty' ;
id = 0 ;
output ;
end ;
run ;
data list_of_meetings ;
length iteration InviterID InvitedID 8. ;
run ;
/****
iter = number of club meetings
hist = length of memory for pairings
tries = number of iterations to pair everyone
****/
%macro loop_coffee (iter=, hist=6, tries= 10) ;
proc sql noprint ;
select max(0,max(iteration)) + 1 into :base
from list_of_meetings ;
quit ;
%do i = &base. %to &iter. ; /* loop through number of meetings */
proc sort data = list_of_meetings (where=(iteration >= &i - &hist )) out = lookup nodupkey ; by InviterID InvitedID ; run ; /* get memory of pairings */
proc sql ; /* list all acceptable pairs */
create table all_pairs as
select a.ID as InviterID, b.ID as InvitedID
from Participants a
inner join Participants b
on a.ID lt b.ID
left join lookup c /* exclude the memory */
on a.ID eq c.InviterID and b.ID eq c.InvitedID
where c.InviterID is NULL ;
quit ;
%let j = 0 ;
%let all_pairs = 0 ;
%do %until (&all_pairs | &j > &tries) ; /* iterate and random sort until all members are paired */
%let j = %eval( &j + 1 ) ;
data all_pairs;
set all_pairs;
randnum = ranuni(12345 + &i + &j);
run;
proc sort data = all_pairs ; by randnum ; run ; /* random sort */
data out_pairs ; /* select the pairs: no. of IDs/2 */
declare hash h() ;
h.defineKey("ID") ;
h.defineDone() ;
do until ( eof1 ) ;
set Participants (keep= ID) end = eof1 ;
rc = h.add () ; /* populate list of members */
end ;
do until ( eof2 ) ;
set all_pairs (keep= InviterID InvitedID) end = eof2 ;
rc1 = h.check (key:InviterID) ;
rc2 = h.check (key:InvitedID) ;
if rc1 = 0 and rc2 = 0 then do ;
rc = h.remove (key:InviterID) ; /* delete member from list if paired */
rc = h.remove (key:InvitedID) ;
output ;
end ;
if h.num_items = 0 then do ;
call symput('all_pairs', 1 ) ;
stop ;
end;
end ;
stop ;
keep InviterID InvitedID ;
run ;
%end ;
data list_of_meetings ;
set list_of_meetings (where=(iteration ne .))
Out_pairs (in=pairs) ;
if pairs then iteration = &i. ;
run ;
%end ;
%mend ;
%loop_coffee (iter=10,hist=6,tries=10) ;