将数组的子集传递给SAS中的mean函数

时间:2014-03-04 15:48:35

标签: arrays sas

我有一个变量数组和一个长度为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;

2 个答案:

答案 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;

这似乎更有效率。