【问题标题】:counters/looping inside a SAS macroSAS宏内的计数器/循环
【发布时间】:2018-01-16 13:54:11
【问题描述】:

我正在教授一门 SAS 课程,并且正在尝试一些模拟。我目前正在尝试模拟棒球阵容。我对宏不是很擅长,并且能够通过多次试验和错误以及之前在此站点上的一些帮助来完成此代码。我希望有人能帮助我到达终点线。

我的目标是能够正确使用计数器。
我正在读取一个有 9 个观察值的数据集,并且有一个名为 cutoff 的变量(它是根据击球手确定击球与否的能力使用的截止值,并将与 randvar 进行比较)。变量“顺序”只是为了让它更容易理解(注意,每 9 个击球手循环一次)。一旦第三次出局(局结束),Count_outs 将出局重置为 0。

我需要能够重复读取这 9 个观察数据集,而我完成它的方式(在前面的一些帮助下)是创建一个名为“out”的数据集,并将其附加到我的数据中按照我下面的方式设置“原点”。

除了少数例外,一切都按我的意愿运行。我想要一个计数器在 27 次补牌后重置为 0。

在 18 次观察之后,它可以按照我的意愿工作,尽管第 19 次观察,请注意第 19 次观察的缺失。因此,当然,我希望第 19 次(及之后的)观察具有一个随机变量(从第 19 次观察开始,每第 9 次观察都会丢失),并相应地更新计数器。

我认为应该很容易解决的另一个问题是计数不会正确。请注意,第一个观察值有一个 randvar = 0.18(小于截止值,这应该会导致 out 并且 count=1。但是,之后它可以正常工作。我已经尝试修改了几十次)。有人可以帮忙吗?

非常感谢

%macro replicate(new,out,n)/des=’&out is &new repeated &n times.’;
  Data & out;
  Set &new;
  %do i=1 %to &n;
    Data &out;
      randvar=uniform(1);
      if randvar<cutoff then do;
        count+1;
        count_outs+1;
      end;
      set &out &new;
      if count_outs=3 then count_outs=0;
      if count=28 then do;
        set &new;
        count=1;
      end;
    run;
  run;
  %end;
%mend;

注意:我尝试显示输出,但无法正确格式化。

【问题讨论】:

  • 如果你的问题更笼统一点会有所帮助。由于棒球不是我来自的“事物”,因此我对此知之甚少,因此很难理解您的问题。你能提供样本数据和所需的输出吗?话虽如此,该代码看起来很奇怪。看起来您将数据步骤放在没有多大意义的数据步骤中。另外我会假设您的第一个 data &amp; out; 语句在这里输入错误,您的意思是 data &amp;out;
  • 感谢您的回复。我确实得到了答案

标签: loops macros sas dataset


【解决方案1】:

您以一种实际上没有必要或不合适的方式使用宏。宏只是编写 SAS 代码 - 所以不要在宏中放入任何不能正常写入的内容,除非它前面有 %。

这里有这样的结构:

data out;
  set in;
  data out; 
    set in out;
  run;
run;

这显然行不通,对吧?外部数据/集将很快结束,然后内部数据/集将运行。

无论如何,您无需执行任何这些操作即可进行模拟。您可以在宏之外执行所有操作。

data out;
  call streaminit(7);           *seed better random number engine;
  do pointvar = 1 by 1 until (outs=27);   *iterate starting at 1 and stop when 27 outs;
    randvar = rand('Uniform');  *better random number engine;
    if pointvar > 9 then pointvar=1;      *reset to 1 if over 9;
    set in point=pointvar;      *pull the row we need;
    if randvar < cutoff then do;
      outs+1;
      outs_inning+1;
    end;
    output;
    if outs_inning=3 then outs_inning=0;
  end;
  stop;
run;

这可以满足您的需求(或多或少,您不提供示例数据,因此我无法测试)。不需要宏;您当然可以根据需要定义任意数量的宏变量(用于 in、out 等)。

【讨论】:

  • 同意。如果您正在教 SAS 课程,我只会教 SAS,而不是宏语言。在您的学生学会了一些 SAS 之后,他们可以自学或在第二堂课中学习宏语言。
  • 你好乔(和昆汀)感谢您的回复。这实际上只是一些学生想要研究的东西(就像我一样),因为我们已经讨论了以概率(p 值等)的方式进行的模拟。乔,我有九个截止数字是 0.74、0.73、0.75、0.70、0.76、0.78、0.75、0.72、0.76。我试过你的代码,可以这么说,它似乎挂了。让它运行 10 分钟或更长时间。似乎有些不对劲。你能在这里测试吗?对不起,我在这里比较新。有没有办法发送带有数字的文件,以便其他人更容易运行它们?再次感谢约翰
  • @GKJohn 最后需要stop;,我省略了。
  • 再次感谢乔的回复。我一直在玩这个(无济于事)并试图让它重复一场比赛,可以这么说,它会在 27 次出局后从阵容顶部开始。因此,就我现在所拥有的而言,假设第 27 次出局是由第 5 次击球手完成的。我想将整个代码放在一个循环中,在该循环中它在数据集的开头再次启动该过程(1sot 观察,即第一个击球手)。所以,假设我想在这里完成 3 次迭代。 3场比赛27场。有没有办法做到这一点?我尝试执行以下操作。 (见下文)
  • %macro replicate(new,out,n)/des='&new1 被 &out 重复 &n 次数据 &new; %do i=1 到 &n;出发;输出; %结尾; %修补; %复制(新,出,3);过程打印;这样做的问题是它只是将每个观察值读取 3 次。所以在 do i=1 到 3 中,接着 set out (3 次从 out 中获取第一个观察值,然后 3 次从 out 中获取第二个观察值,依此类推,即 Outs randvar cutoffouts_inning 0 .84 .73 0 0 .84 .73 0 0 .84 .73 0 1 .61 .75 0 1 .61 .75 0 1 .61 .75 0 thx
猜你喜欢
  • 2019-04-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多