1

好的,这似乎是一件非常简单的事情,但我无法解释 sas datastep 中的“by statement”到底在做什么。我知道什么时候需要使用它,但我不确定它在做什么。

在下面的示例中,我了解 first.var 和 last.var 的虚拟 sas 列是什么,当它具有它的值时。by 语句是否在 var initial 和 metal 周围创建了这些虚拟列?那么sas是扫描整个数据集一次呢?

data jewelers ;
  input id initial $ metal $ ;
datalines;
456 D Gold
456 D Silver
123 L Gold
123 L Copper
123 L PLatinum
567 R Gold
567 R Gold
567 R Gold
345 A Platinum
345 A Silver
345 A Silver
;

proc sort ;
  by initial metal ;
run;

data dups;
  set jewelers ;
  by initial metal ;                           
  if not (first.metal and last.metal) then output;
run;

如果我 proc print dups 我希望这样:

567 R Gold
567 R Gold
567 R Gold
345 A Silver
345 A Silver
4

2 回答 2

2

正如您所承认的,SAS 正在为您的语句first.byvarlast.byvar的每个变量创建自动变量。从语句中读入的记录在 SAS 将它们移动到 PDV(程序数据向量 - 在输出之前在每一行上执行数据步骤逻辑)之前保存在缓冲区中,因此 SAS 可以提前查看缓冲区中的下一条记录查看是否有任何 byvars 已更改,并为当前在 PDV 中的行设置。byvarbysetlast.byvar = 1

我可以看到您所说的您期望的内容与您在 dups 数据集中获得的内容之间的唯一区别是记录的顺序 - 因为您先按初始排序,然后按金属排序,所以A Silver记录在记录之前排序R Gold

如果您想在保留原始行顺序的同时跨这两个变量获取重复项,则需要记下原始记录顺序,并在您的第二个数据步骤之后将您的重复数据集重新排序为该顺序。

于 2015-07-04T09:15:03.710 回答
0

SAS 基本上是将当前记录与之前和之后的记录进行比较来计算 FIRST。最后。标志。如果你愿意,你可以自己滚动。

data test ;
   set jewelers end=eof;
   by initial metal ;
   if not eof then 
      set jewelers (firstobs=2 keep=initial metal 
                    rename=(initial=next_initial metal=next_metal))
   ;
   first_initial = (_n_=1) or (initial ne lag(initial));
   last_initial = eof or (initial ne next_initial) ;
   first_metal = first_initial or (metal ne lag(metal)) ;
   last_metal = last_initial or (metal ne next_metal);
   put / (initial metal) (=);
   put (first:) (=);
   put (last:) (=);
run;
于 2015-07-04T15:23:47.210 回答