在SAS中使用数组

时间:2015-08-05 18:31:04

标签: arrays sas

我是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;

我正在尝试使用数组重做这个,这可能吗?例如。将它存储在某个全局数组中并稍后访问它......

2 个答案:

答案 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指出的格式或其他几种选项 - 但我认为这些是最简单的。