我的数据是这样的
testA testB testC
XYZ 1
XYZ 2 ABC
XYZ 3
XYZ 4 BCA
XYZ 5
ZYX 2
ZYX 3 LMN
ZYX 4
ZYX 5
YZX 1
YZX 2
对于每个唯一值(first.testA),我想获取testB的最小值的缺失值testB.But,如果没有非缺失值。我只想让它有第一行对于那个组合。换句话说,我希望我的最终结果看起来像这样
XYZ 2 ABC
ZYX 3 LMN
YZX 1
我确实得到了我想要的使用datastep和宏编程,但它非常紊乱和乏味,因为我有很多变量我想做这个。我想知道是否有更简单的方法
dataset test001;
proc sort data=test001; by testA testB testC; run;
proc sort data=test001 nodupkey ; by testA; run;
data test002;
set test001;
if missing(testC) then output missing001;
run;
data test003;
merge test001
missing001;
by testA;
run;
proc sort data=test001; by testA testB testC; run;
proc sort data=test001 nodupkey ; by testA; run;
答案 0 :(得分:0)
在这里,你需要的是有效的两次数据传递:一个用于识别id-groups(testA组),它们有一个有用的testC行,另一个用于获取那些没有&#的第一行39;吨
在数据步骤中,有两种方法可以立即呈现给我。如果您对此更加满意,PROC SQL也可以轻松实现这一目标。
最简单的方法是创建一个从未拥有testC记录的记录的数据集,然后将其合并回主数据集。这看起来与你正在做的很接近,但这种方式要快一点。
proc sort data=have;
by testa testb;
run;
data have_notestC;
set have;
by testA;
if first.testA then testCcount = 0; *for each testA group reinitialize the counter;
if not missing(testC) then testCcount+1; *if you see a testC then update counter;
if last.testA and testCcount=0 then output;*if counter=0 then you never hit testC;
run;
data want;
merge have have_notestC(in=_ntc);
by testA;
if first.testA then testCcount=0; *reinitialize counter;
if _ntc and first.testA then output; *if it was a _ntc record then it has no testC;
else if _ntc then delete; *if not first.testA and _ntc then uninteresting;
else if testCcount = 0 and not missing(testC) then do;
testCcount+1; *if testCcount=0 and testC is present then you want it;
output;
end;
*otherwise ignore;
run;
更有效但更困难的方法是双DoW循环。它反映了合并解决方案,但是在一个datastep中完成。它的效率更高,因为两次传递数据都是在磁盘读取中完成的,假设您的BY组大小足够小 - 如果值全部在一起,则无需排序即可完成#&# 39;但不一定按字母顺序排列(如您的数据在上面 - YZX在ZYX之后,但每个testA值的所有行都是连续的。)
data want;
testCcount=0;
hasOutput=0;
do _n_ = 1 by 1 until (last.testA);
set have;
by testA notsorted;
if not missing(testC) then testCcount=1;
end;
do _n_= 1 by 1 until (last.testA);
set have;
by testA notsorted;
if first.testA and testCcount=0 then output;
else if testCcount=0 then delete;
else if hasOutput=0 and not missing(testC) then do;
output;
hasOutput=1;
end;
end;
run;
如果你有许多你正在使用的变量,这些都不一定能让你很容易处理事情,虽然DoW循环版本可以为多个变量运行(但不容易作为宏运行,因为你需要为您要添加的每个变量在多个位置更改内容。我并不完全清楚如何通过众多变量来实现这一目标'无论如何(因为输出是一个基于行的东西),但它可以根据细节进行调整。