【问题标题】:What is a by statement really doing in a sas data step?by 语句在 sas 数据步骤中真正做了什么?
【发布时间】:2015-07-04 05:10:55
【问题描述】:

好吧,这似乎是一件非常简单的事情,但我无法解释 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

【问题讨论】:

  • 在您的示例中,first.idlast.id 未初始化,因为它们未出现在 by 语句中。要查看创建了哪些隐藏变量,请在 by 语句之后添加 put _all_; 语句。 (仅对小型数据集执行此操作,因为它有可能填满日志)。

标签: duplicates sas datastep


【解决方案1】:

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

我可以看到你所说的你所期望的和你在 dups 数据集中得到的唯一区别是记录的顺序 - 因为你已经按初始排序然后金属排序,A Silver 记录排序在前面R Gold 记录。

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

【讨论】:

    【解决方案2】:

    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;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-13
      • 1970-01-01
      • 2022-08-14
      • 1970-01-01
      • 2014-12-22
      • 1970-01-01
      相关资源
      最近更新 更多