2016-07-05 151 views
1

我在C#中试过这个,但没有太多成功。所以我现在正在尝试SAS。使用EG会话和我的SAS代码,我们与SASHELP.CLASS中的学生列表一起工作。 这些人希望彼此了解对方,并每月随机配对一起在咖啡日期。SAS:咖啡人?

规则: 随机生成咖啡日期列表每月生成; 我将每个月的配对存储到我每月追加的历史数据集中。

一个人在6个月的时间内不能与同一人一起喝咖啡。因此,我们保持历史的目的的独立数据集3个瓦尔: LastDate,InviterID,InvitedID

我们核对历史列表中的每个配对,而我们只有最后的6个月的数据加载到一个临时数据集用于检查的目的。

如果找不到最近匹配的对,则将新匹配对添加到新的配对数据集中,并从原始参与者数据集中删除2个名称(行),直到数据集少于2行。 (一个人不能与另一个人配对)

不幸的是,我们在这个列表中有19个人,所以一个人将被排除在外,直到我们可以添加一个新的参与者。有人有兴趣加入我们的咖啡俱乐部吗? :-)

所以我通过派生和数据集ID(ñ)开始,我只保留名称

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; 

但我卡住:-( 我需要休息,请帮助...

有其他人做这种类型的成功之前随机配对?我在这里抓救命稻草...... 任何帮助非常赞赏。 莱恩

回答

1

这是我的想法,这是远远效率。尤其,当NOBS越来越大,因为有一个CARTES涉及伊恩产品。此外,我在这种情况下添加了另一行,从而欺骗了奇数。

  1. 准备数据并生成空的结果表。
  2. 创建不包括最近配对的所有可能配对(组合)的列表。
  3. 随机排序并通过列表下降,直到每个元素被选取一次。
  4. 追加到结果表。

有一个缺点,因为有可能会有成员谁不会配对,因为所有可能的合作伙伴已被挑选。为了避免我们可以迭代,直到我们得到最大的配对。编辑:添加迭代。现在该程序会随机抽取,直到每个人都匹配或达到阈值。

这个问题应该可能在像矩阵定向语言IML或R中实现。

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) ;