我有一个变量数组和一个长度为77的标志数组。对于每次观察,标志数组由连续的0组成,后跟连续的1(即,在标志为1之后,全部稍后索引处的标志是一个)。我试图计算变量数组的平均值/标准/最小值/最大值,其对应的标志是0.这是我的宏:
%macro meanof_precancel(input, meanstat);
j = 77;
do i = 1 to 77;
if cancelled_{i} = 1 then do;
j = i - 1;
call symputx('lastactive', j);
leave;
end;
end;
if j = 0 then &meanstat = 0;
else &meanstat = mean(of &input.1-&input.&lastactive);
%mend;
我很难找到解决问题的方法:
else &meanstat = mean(of &input.1-&input.&lastactive);
对于j = 33:
,是否有人有策略将其解析为以下内容: else mean_stats = mean(of total_1-total_33);
提前致谢。
我最后使用了另一种方法,尽管它需要创建77个新变量。我创建了一个新数组,只要相应的标志为1,就会将每个值设置为缺失,并采用这个新数组的平均值。对于那些感兴趣的人:
%macro meanof_precancel(input, meanstat);
array &input.temp{77};
do i = 1 to 77;
if not cancelled_{i} then
&input.temp{i} = &input{i};
else &input.temp{i} = .;
end;
&meanstat = mean(of &input.temp{*});
%mend;
答案 0 :(得分:1)
如你所知,你只能将整个数组的值加起来,以及你遇到问题的原因:
else &meanstat = mean(of &input.1-&input.&lastactive);
是因为在datastep完成之前,宏中较早的调用symputx才会执行。
这是相应的SAS文档:
在尝试之前尝试引用SYMPUT分配的值时出现问题 可用
使用SYMPUT最常见的问题之一是尝试引用 在该变量之前由SYMPUT分配的宏变量值 创建。失败通常是因为声明而发生的 在执行CALL之前引用宏变量进行编译 指定变量值的SYMPUT语句。最重要的 在使用SYMPUT时要记住的事实是它分配了值 程序执行期间的宏变量,但宏变量引用 在编译步骤期间解决,使用全局语句 在步骤之外,或SCL程序。
结果:•您不能使用 宏变量引用,用于检索宏变量的值 SYMPUT创建该宏变量的相同程序(或步骤) 并赋予它一个价值。
http://support.sas.com/documentation/cdl/en/mcrolref/61885/HTML/default/viewer.htm#a000210266.htm
这会破坏原始数据所以我会小心,但它将允许从原始数组计算std / mean / min / max等。
%macro precancel_stat(input, statvar, stat);
j = 77;
do i = 1 to 77;
if cancelled_{i} = 1 then do;
j = i - 1;
do k=i to 77;
&input.{k}=.;
end;
i=77;
end;
end;
if j = 0 then &statvar = 0;
else &statvar = &stat.(of &input.{*});
%mend;
/* test datasets*/
data test;
array sum_me{77} sum1 - sum77;
array cancelled_{77} cancelled1 - cancelled77;
do k=1 to 10;
do i =1 to 77;
sum_me{i}=i;
if i lt 33+k then cancelled_{i}=0; else cancelled_{i}=1;
end;
output;
end;
run;
/* test the macro call*/
data testit ;
set test (drop= i k );
array sum_me{77} sum1 - sum77;
array cancelled_{77} cancelled1 - cancelled77;
%precancel_stat(sum_me,meanstat,mean);
%precancel_stat(sum_me,StDev,STD);
%precancel_stat(sum_me,MinVal,Min);
%precancel_stat(sum_me,MarVal,Max);
%precancel_stat(sum_me,SumVal,sum);
run;
proc print data=testit;
run;
答案 1 :(得分:1)
你不能那样使用call symput
,因为时机错了;您需要在编译期间知道&lastactive.
的值,但在查看数据之前,您实际上并不知道它。
您当然可以使用辅助数组执行此操作。我会为此目的使用temporary
数组,如果您要这样做(array &input.temp[77] _temporary_;
),因为它不会无用地写入最终数据集并且仅驻留在内存中。
老实说,你可能最好只有两个变量,即均值变量和一个计数器(你的j
已经是基本的)。而不是把它放在临时数组中,只需
meanvar=meanvar+input[i];
然后在循环结束时
meanvar=meanvar/j;
这似乎更有效率。