在SAS中重复一个宏

在SAS中重复一个宏,sas,Sas,我试图从下面的数据集(test2)中随机选择6个案例。必须按照ED、CCM、MAT、CAC的特定顺序选择案例。第一张通行证来自付款人1(P1),第二张通行证来自付款人2(P2),直到我总共收到6个案例。在每个度量类型中,首先选择随机数最低的情况。下面是我正在使用的宏,我希望能够由付款人重复 ID Measure Payer 1439 CAC P1 1135 CCM P1 1736 ED P1 1737 MAT P1 1738 CCM P2 2351 ED P2 42

我试图从下面的数据集(test2)中随机选择6个案例。必须按照ED、CCM、MAT、CAC的特定顺序选择案例。第一张通行证来自付款人1(P1),第二张通行证来自付款人2(P2),直到我总共收到6个案例。在每个度量类型中,首先选择随机数最低的情况。下面是我正在使用的宏,我希望能够由付款人重复

ID  Measure Payer
1439  CAC  P1
1135  CCM  P1
1736  ED   P1
1737  MAT  P1
1738  CCM  P2
2351  ED   P2
4251  ED   P1


DATA CAC CCM ED MAT;
set test2;
    if measure = 'CAC' then output CAC;
else if measure = 'CCM'  then output CCM;
else if measure = 'ED' then output ED;
else if measure = 'MAT' then output MAT;
RUN;


%MACRO select (dsn,num);

DATA &dsn;
  set &dsn;

  min_random=min(random);
RUN;
PROC SORT data=&dsn;
  by Payer min_random;
RUN;
DATA &dsn;
   set &dsn;
   if _N_ le #
RUN;

 %MEND select;

%SELECT(ED,1);  %SELECT(CCM,1);  %SELECT(MAT,1); %SELECT(CAC,1); 

DATA sample1A;
set ED CCM MAT CAC;
RUN;
对于上述样本数据集,应使用6个案例的输出

1736  ED   P1
1135  CCM  P1
1737  MAT  P1
1439  CAC  P1
2351  ED   P2
1738  CCM  P2

我试图通过以下方式解决这个问题:

  • 计算获取记录数所需的完整循环数。每个循环将获取4条记录(分别用于ED、CCM、MAT、CAC)。在你的情况下是1
  • 计算获取记录数所需的半循环数。在您的情况下,ED和CCM各有两个
  • 下面是代码,这几乎是不言自明的


    创建示例数据集

    data test2;
    infile datalines;
    input ID Measure $ Payer $;
    datalines;
    1439  CAC  P1
    1135  CCM  P1
    1736  ED   P1
    1737  MAT  P1
    1738  CCM  P2
    2351  ED   P2
    4251  ED   P1
    ;
    run;
    
    
    DATA CAC CCM ED MAT;
    set test2;
        if measure = 'CAC' then output CAC;
    else if measure = 'CCM'  then output CCM;
    else if measure = 'ED' then output ED;
    else if measure = 'MAT' then output MAT;
    RUN;
    
    
    %MACRO select (dsn,num);
    
    DATA &dsn;
      set &dsn;
    
      min_random=ranuni(0);
    RUN;
    PROC SORT data=&dsn;
      by Payer min_random;
    RUN;
    DATA &dsn;
       set &dsn;
       if _N_ le #
    RUN;
    
    proc append base=sample1A data=&dsn. force;
    run;
    
    %MEND select;
    
    %macro loop;
    
    %let inp=ED,CCM,MAT,CAC;
    %let Num_of_records_to_extract=6;
    %let Num_of_distinct_measure=4;
    
    data _NULL_;
    loop_count=int(&Num_of_records_to_extract./&Num_of_distinct_measure.);
    semi_loop_count=mod(&Num_of_records_to_extract.,&Num_of_distinct_measure.);
    call symputx("loop_count",loop_count);
    call symputx("semi_loop_count",semi_loop_count);
    run;
    
    %if &loop_count. ge 1 %then %do;
       %do i=1 %to &loop_count.; 
           %do j=1 %to 4;
              %SELECT(%sysfunc(scan("&inp.",&j.,",")),1);  
            %end;
        %end;
    %end;
    
    %if &semi_loop_count. ge 1 %then %do;
           %do k=1 %to &semi_loop_count.;
              %SELECT(%sysfunc(scan("&inp.",&k.,",")),1);  
            %end;
    %end;
    
    
    %mend;
    %loop;
    

    以下是我是如何做到这一点的

    data test2;set test2;
    ran=ranuni(123);
    if measure='ED' then order=1;
    if measure='CCM' then order=2;
    if measure='MAT' then order=3;
    if measure='CAC' then order=4;
    run;
    
    proc sort data= test2 out=P1;
    by order payer ran;
    where payer='P1';
    run;
    
    proc sort data= test2 out=P2;
    by order payer ran;
    where payer='P2';
    run;
    
    data S1 S3;set P1;
    by order ran;
    if first.order then output S1;else
    output S3;
    run;
    
    data S2 S4;set P2;
    by order ran;
    if first.order then output S2;else
    output S4;
    run;
    
    data sample;
    set S1 S2 S3 S4;
    run;
    
    data sample;set sample (obs=6);
    run;
    

    也有不那么繁忙的方式。任何时候,只要可以通过组处理而不是宏循环来使用,就应该。在这种情况下,不需要将数据集分成很多部分来完成这项工作,如果数据集很大,就I/O而言,这是非常昂贵的

    这是一个易于维护的解决方案。。。未测试:

        %let SAMPLE_SIZE=6 ;
    
        proc format ; 
           value $measure2order
            'ED'  = '1'
            'CCM' = '2'
            'MAT' = '3'
            'CAC' = '4'
            other = 'X'
               ; run;
    
        *--- changing dataset name because I am tossing  ---* ;
        *---    records with unexpected values (or more  ---* ;
        *---    specifically, measures that are not      ---* ;
        *---    needed for this particular sample.)      ---* ;
        data SAMPLE 
             ODD_STUFF ;
        set test2 ;
           random=ranuni(123) ;
           order=put(measure,$measure2order.) ;
           if order='X' then output ODD_STUFF ;
           else output SAMPLE ;
           run; 
    
           proc sort data=SAMPLE ;
              by payer order random ;
              run;
    
              data SAMPLE ;
              set SAMPLE ;
              by payer order random ;
                 if first.order ;
                 sample_count+1 ;
                 output ;
                 if sample_count GE &SAMPLE_SIZE then stop ; 
                 drop random sample_count ;
                 run; 
    

    (顺便注意……这里的问题定义似乎有点古怪。假设您有一组好的数据,您的样本将为付款人=1的四个度量值中的每一个随机记录,为付款人=2的前两个度量值中的每一个随机记录。)

    什么是PMT_SRC_组?您是否执行了代码?最小随机=最小(随机);这不起作用,我将在这里放置另一个随机函数。我希望您理解,因为您使用的是随机数,所以您可能无法获得与您在此处发布的相同的输出,可能有两个1736 EDs或1135 CCM!!,只有ED、CCM、MAT、CAC的顺序是固定的。我确实执行了我的代码,最小值(随机)工作。我知道,由于我使用的是随机数,取决于种子,结果会有所不同。但我需要首先选择具有最低随机数的度量(类别)的记录,并需要通过付款人重复该过程,以获得总共6个随机案例。所有奇数通行证适用于付款人1,偶数通行证适用于付款人2。我没有修改您的逻辑。请参见下文。相同的情况在示例中不能重复