我正在尝试使用数组来完成以下操作。但是,我之前从未使用过,我遇到了一些麻烦。
基本上我想获取以下数据并为每个acct,seq1,seq2组合创建一行(观察):
acct seq1 seq2 la ln
9999 1 10 20.01 100
9999 1 10 19.05 1
9999 2 11 26.77 100
9999 2 11 24.86 1
8888 3 20 38.43 218
8888 3 20 37.53 1
这就是我想要的结果。注意,为了空间,我只显示la1到la3和ln1到ln3。它实际上将转到la7和ln7:
acct seq1 seq2 la1 la2 la3 ln1 ln2 ln3
9999 1 10 20.01 19.05 . 100 1 .
9999 2 11 26.77 24.86 . 100 1 .
8888 3 20 38.43 37.53 . 218 1 .
这是我到目前为止尝试过的代码。任何帮助将不胜感激:
data want;
set have;
by acct seq1 seq2;
if first.seq2 then do;
array la_array {7} la1-la7;
array ln_array {7} ln1-ln7;
end;
do i = 1 to 7;
la_array(i)=la;
ln_array(i)=ln;
end;
run;
答案 0 :(得分:4)
我走另一条路线,利用PROC SUMMARY(或MEANS)中的一些小功能来实现这一目标。输出表按ACCT排序,因为这是CLASS语句中的第一个变量,显然您可以在之后轻松按SEQ1顺序求助。
IDGROUP语句与OUT [7]一起为列出的每个变量(LA,LN)创建7个变量,并在读取数据时按顺序填充它们。 AUTONAME选项将序号添加到变量名称(例如LN1,LN2,...,LN7)。我在这种方法中遇到的唯一问题是源数据集非常大的服务器上的内存不足错误,这是由于PROC SUMMARY在内存中运行。希望在这种情况下它会对你有用。
proc summary data=have nway;
class acct seq1 seq2;
output out=want (drop=_:)
idgroup(out[7] (la ln)=) / autoname;
run;
答案 1 :(得分:1)
好的......你必须记住,SAS阵列通常不是真正的向量或内存变量数组,就像大多数其他语言一样。它们只是数据集变量的占位符。
也就是说,ARRAY语句就是用来定义数据集变量和速记数组引用之间的映射。把它放在放置它的位置是没用的,因为它没有初始化任何东西。
您应该考虑的另一件事是您需要累积值并写一行。由于尚未读取所有数据,因此您无法在FIRST行上执行此操作。你必须使用最后一次。
第三个问题是,您定义的新变量必须在读取另一行时保留该值。 SAS通常会将输入数据集中没有的所有变量重置为MISSING。要避免这种情况并在一组行上累加sum,min,max或其他值,必须使用RETAIN语句。
最后......您可能希望删除刚刚用于计算的任何变量,但在输出数据集中不需要..." i"在这种情况下。
我认为这应该可以满足您的需求:
DATA want (DROP=i);
SET have;
BY acct seq1 seq2;
/* define variables */
ARRAY la_array {7} la1-la7;
ARRAY ln_array {7} ln1-ln7;
RETAIN i la1-la7 ln1-ln7;
IF FIRST.seq2 then do;
/* initialize group variables */
DO i = 1 to 7;
la_array(i)=.;
ln_array(i)=.;
END;
/* initialize index variable */
i = 1
END;
/* read input row values into array variables */
la_array(i)=la;
ln_array(i)=ln;
i = i + 1;
/* write output row if group is finished */
IF LAST.seq2;
RUN;
不幸的是,我目前没有可用的SAS安装......你必须尝试一下,让我知道它是怎么回事。