保持采样宏变量常数

时间:2015-02-19 18:09:07

标签: sas sas-macro sas-iml

希望是一个简单的答案。我正在做一个模拟研究,在那里我需要从一个统一分布U(25,200)中抽取随机数量的个体N,每次重复一千次。一次复制的代码如下所示:

%LET U = RAND("UNIFORM");
%LET N = ROUND(25 + (200 - 25)*&U.);

我在DATA步骤之外创建了这两个宏变量,因为我需要在后续的DATA步骤和SAS和IML中的DO循环中重复调用N变量。

问题是每次我在复制中调用N时,它会重新采样U,这必然会修改N.因此,N在复制中不保持不变。此问题显示在下面的代码中,其中我首先创建N作为变量(对于个体是恒定的)并使用DO循环为每个个体的X采样预测值。请注意,N中的值与个人总数不同,这也是一个问题。

DATA ID; 
    N = &N.;
    DO PersonID = 1 TO &N.;
        X = RAND("NORMAL",0,1); OUTPUT;
    END;
RUN;

我猜我需要做的是以某种方式在整个复制过程中保持U不变,然后允许对其进行重新采样以进行复制2,依此类推。通过保持U不变,N必然保持不变。

有没有办法使用宏变量来做到这一点?

3 个答案:

答案 0 :(得分:0)

我不确定如何在宏世界中这样做,但这就是你可以将代码转换为数据步骤以完成同样的事情。

关键是使用CALL STREAMINIT设置随机数流初始化值。

Data _null_;
call streaminit(35);
u=rand('uniform');
call symput('U', u);
call symput('N',  ROUND(25 + (200 - 25)*U));
run;


%put &n;
%put &u;

答案 1 :(得分:0)

&N不存储值。 &N存储代码“ROUND(...(RAND ...”等)。你在滥用宏变量,这里:虽然你可以在&N中存储一个你没有这样做的数字;你必须使用%sysfunc,无论哪种方式,这都不是正确答案。

首先,如果您反复抽样重复,请查看论文Don't be Loopy',其中包含一些应用程序。还要考虑Rick Wicklin的论文Sampling with Replacement,以及他所引用的那本书(“在SAS中模拟数据”)也很好。如果您在一个样本一个执行模型上运行您的流程,那么这是一个缓慢且难以处理的方式。立即进行所有重复,立即处理所有重复; IML和SAS都很乐意为您做到这一点。你的统一随机样本大小有点难以使用,但它并非难以克服。

如果你必须按照你的方式进行,我会要求数据步骤创建宏变量,如果有理由这样做的话。在示例的最后,您可以使用call symput来计算N. IE的值:

%let iter=7; *we happen to be on the seventh iteration of your master macro;
DATA ID;
    CALL STREAMINIT(&iter.); 
    U = RAND("UNIFORM");
    N = ROUND(25 + (200 - 25)*U);
    DO PersonID = 1 TO N;
        X = RAND("NORMAL",0,1); 
        OUTPUT;
    END;
    CALL SYMPUTX('N',N);
    CALL SYMPUTX('U',U);
RUN;

但同样,单数据步骤模型可能是您最有效的模型。

答案 2 :(得分:0)

Joe指出,执行此模拟的有效方法是在单个数据步骤中生成所有1000个样本,如下所示:

data AllSamples;
call streaminit(123);
do SampleID = 1 to 1000;
   N = ROUND(25 + (200 - 25)*RAND("UNIFORM"));
   /* simulate sample of size N HERE */
   do PersonID = 1 to N;
      X = RAND("NORMAL",0,1);   
      OUTPUT;
   end;
end;
run;

这确保了随机数流的独立性,并且生成1000个样本需要几分之一秒。然后,您可以使用BY语句分析每个样本的统计数据的抽样分布。例如,以下对PROC MEANS的调用输出1000个样品中每个样品的样品大小,样品平均值和样品标准偏差:

proc means data=AllSamples noprint;
by SampleID;
var X;
output out=OutStats n=SampleN mean=SampleMean std=SampleStd;
run;

proc print data=OutStats(obs=5);
var SampleID SampleN SampleMean SampleStd;
run;

有关为什么BY组方法更有效(总时间=小于1秒!)的详细信息,请参阅文章"Simulation in SAS: The slow way or the BY way."