by 语句在 sas 数据步骤中真正做了什么?
What is a by statement really doing in a sas data step?
好吧,这似乎是一件非常简单的事情,但我无法解释 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 打印重复,我希望这样:
567 R Gold
567 R Gold
567 R Gold
345 A Silver
345 A Silver
如您所知,SAS 正在为您的 by
语句中的每个 byvar
创建自动变量 first.byvar
和 last.byvar
。从 set
语句中读入的记录在 SAS 将它们移动到 PDV(程序数据向量 - 输出前在每一行上执行数据步骤逻辑)之前保存在缓冲区中,因此 SAS 可以向前看缓冲区中的下一条记录以查看是否有任何 byvars 已更改,并为当前在 PDV 中的行设置 last.byvar = 1
。
我能看到你所说的你期望的和你在 dups 数据集中得到的唯一区别是记录的顺序 - 因为你已经按初始和金属排序,A Silver
记录排在 R Gold
条记录之前。
如果您想在保留原始行顺序的同时获取这两个变量的重复项,则需要记下原始记录顺序,并在第二个数据之后将重复数据集排序回该顺序步骤.
SAS 基本上是将当前记录与之前和之后的记录进行比较,以计算第一个记录。最后。旗帜。如果需要,您可以自己滚动。
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;
好吧,这似乎是一件非常简单的事情,但我无法解释 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 打印重复,我希望这样:
567 R Gold
567 R Gold
567 R Gold
345 A Silver
345 A Silver
如您所知,SAS 正在为您的 by
语句中的每个 byvar
创建自动变量 first.byvar
和 last.byvar
。从 set
语句中读入的记录在 SAS 将它们移动到 PDV(程序数据向量 - 输出前在每一行上执行数据步骤逻辑)之前保存在缓冲区中,因此 SAS 可以向前看缓冲区中的下一条记录以查看是否有任何 byvars 已更改,并为当前在 PDV 中的行设置 last.byvar = 1
。
我能看到你所说的你期望的和你在 dups 数据集中得到的唯一区别是记录的顺序 - 因为你已经按初始和金属排序,A Silver
记录排在 R Gold
条记录之前。
如果您想在保留原始行顺序的同时获取这两个变量的重复项,则需要记下原始记录顺序,并在第二个数据之后将重复数据集排序回该顺序步骤.
SAS 基本上是将当前记录与之前和之后的记录进行比较,以计算第一个记录。最后。旗帜。如果需要,您可以自己滚动。
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;