SAS数据步First Dot自动变量使用异常,求解BY语句分组逻辑问题
搞定SAS First.自动变量和BY分组的问题
嘿,我来帮你理清楚为什么First.自动变量没给你预期结果——核心问题大概率是BY语句的分组逻辑和你实际想要的分组不匹配,咱们一步步拆解:
先搞懂First.自动变量的本质
SAS里的First.<变量>和Last.<变量>是只能在带有BY语句的DATA步里生成的自动变量,它们的规则很简单:
- 当当前观测是
BY语句中某个分组变量的第一个观测时,First.<变量>=1,否则为0 - 同理,
Last.<变量>=1表示当前观测是该分组的最后一个,否则为0 - 注意:BY语句里的变量顺序会影响分组层级——比如
by ssn acct_num会先按SSN大分组,每个SSN下再按ACCT_num小分组
你的现有代码问题分析
看你写的排序语句:
proc sort data=testing out=tst; by ssn acct_num id descending yymm ; run;
你把id和yymm也放进了排序关键字,但如果你的目标是按SSN+账号(ACCT_num)分组,取每个账号下最新的记录,那你的final数据步里的BY语句应该只写到ssn acct_num,而不是把id、yymm也加进去——不然SAS会把id和yymm也当成分组维度,导致First.变量触发的逻辑和你预期的不一样。
修正后的代码示例
假设你想要的是每个SSN+ACCT_num组合下,保留最新YYMM的那条记录,那可以这么写:
data testing; input SSN ACCT_num YYMM ID $; datalines; 123456789 987654321 1801 1 123456789 987654321 1711 9 123456789 476543218 1801 2 123456789 476543218 1711 10 ; run; proc sort data=testing out=tst; /* 按SSN+账号分组,组内按YYMM降序(最新的在前) */ by ssn acct_num descending yymm ; run; data final; set tst; /* 这里的BY语句只指定到你想要的分组维度:SSN+ACCT_num */ by ssn acct_num; /* 只保留每个分组的第一条(也就是YYMM最大的那条) */ if first.acct_num then output; run;
验证逻辑
排序后的tst数据集顺序是:
| SSN | ACCT_num | YYMM | ID |
|---|---|---|---|
| 123456789 | 987654321 | 1801 | 1 |
| 123456789 | 987654321 | 1711 | 9 |
| 123456789 | 476543218 | 1801 | 2 |
| 123456789 | 476543218 | 1711 | 10 |
在final数据步里,first.acct_num会在每个ACCT_num的第一条观测时为1,所以最终输出的就是两条最新的记录:YYMM=1801的那两行。
如果你的预期不是取最新记录,而是其他逻辑,只要调整BY语句的分组变量和First.的判断条件就行——核心就是BY语句的变量必须和你想要的分组完全匹配。
内容的提问来源于stack exchange,提问作者DukeLuke
相关产品推荐
相关产品推荐

