我是SAS初学者。我的代码中有一个类似数组的数据,需要传递给代码中低得多的不同数据步骤来进行计算。我的代码做了类似的事情(本例简化了计算):
data _null_;
call symput('numRuns', 10000);
run;
/* this is the pre-computation step, building CompressArray for later use */
data _null_;
do i = 1 to &numRuns;
value = exp(rand('NORMAL', 0.1, 0.5)));
call symput(compress('CompressArray'||i), value);
end;
run;
data reportData;
set veryLargeDataSet; /* 100K+ observations on 30+ vars */
array outputValues[10000];
do i = 1 to &numRuns;
precomputedValue = symget(compress('CompressArray'||i));
outputValues[i] = /* calculation using precomputedValue */
end;
run;
我正在尝试使用数组重做这个,这可能吗?例如。将它存储在某个全局数组中并稍后访问它......
答案 0 :(得分:4)
SAS中的数组仅在创建它们的数据步骤期间存在。您需要将数组的内容保存在数据集中,或者如您所做的那样,将其保存在一系列宏变量中。
或者,您可以重写一些代码,以便在一个数据步骤中完成使用该数组的所有工作。在这方面,DOW循环非常好。
根据您问题的更新,听起来好像您可以使用临时数组来做您想做的事情:
data reportData;
set veryLargeDataSet; /* 100K+ observations on 30+ vars */
array outputValues[&numruns];
array precomputed[&numruns] _temporary_;
if _n_ = 1 then do i = 1 to &numruns;
if i = 1 then call streaminit(1);
precomputed[i] = exp(rand('NORMAL', &meanNorm, &stDevNorm));
end;
do i = 1 to &numRuns;
outputValues[i] = /* calculation using precomputed[i] */
end;
run;
将数组定义为_temporary_
会导致数组元素的值在数据步骤的迭代中保留,因此您只需填充一次,然后就可以将其用于其余的数据步骤
答案 1 :(得分:2)
有很多方法可以做到这一点,但哈希表查找是最简单的方法之一。
%let meannorm=5;
%let stDevNorm=1;
%let numRuns=10000;
/* this is the pre-computation step, building CompressArray for later use */
data my_values;
call streaminit(7);
do i = 1 to &numRuns;
Value= rand('Normal',&meannorm., &stDevNorm.);
output;
end;
run;
data reportData;
if _n_=1 then do;
declare hash h(dataset:'my_values');
h.defineKey('i'); *the "key" you are looking up from;
h.defineData('value'); *what you want back;
h.defineDone();
call missing(of i value);
end;
set sashelp.class; /* 100K+ observations on 30+ vars */
array outputValues[10000];
do i = 1 to &numRuns;
rc=h.find();
outputValues[i] = value;
end;
run;
基本上,你需要加载'以某种方式表格并用它做某事。这是一个简单的方法。
在您的特定示例中,还有另一种非常简单的方法:将其置于as数组中。
在这种情况下,我们不会输出10k行,而是10k变量 - 然后在新数据步骤中将其声明为数组(再次)。 (如用户667489所述,数组是瞬态的;它们不会以任何方式存储在数据集中,除非作为基础变量,因此必须重新声明每个数据步骤。)
%let meannorm=5;
%let stDevNorm=1;
%let numRuns=10000;
/* this is the pre-computation step, building CompressArray for later use */
data my_values;
call streaminit(7);
array values[&numruns.];
do i = 1 to &numRuns;
Values[i]= rand('Normal',&meannorm., &stDevNorm.);
end;
run;
data reportData;
if _n_=1 then set my_values(drop=i);
set sashelp.class; /* 100K+ observations on 30+ vars */
array outputValues[&numruns.];
array values[&numruns.]; *this comes from my_values;
do i = 1 to &numRuns;
outputValues[i] = values[i];
end;
drop values:;
run;
这里注意我仍然在if _n_=1
中设置了 - 否则它会在第一次迭代后终止数据步骤。
您也可以使用Reeza指出的格式或其他几种选项 - 但我认为这些是最简单的。