4

这个问题与大型机上的 SAS 有关,尽管我相信它在这种情况下并没有什么不同。

我有以下 SAS 数据集:

Obs     DATO    T_ALLOC    T_FRESP

 1     19328      647        1804 
 2     19359      654        1797 
 3     19390      662        1789 
 4     19418      676        1774 
 5     19449      636        1815 
 6     19479      698        1753 

我的目标是将 3 个变量的所有 6 个观察值(我希望我在这里使用正确的术语)放入单独的数组中。

我已经努力阅读有关使用数组的内容,但由于某种原因,我无法解决这个特定问题的解决方案。

如果有人愿意提供帮助,将不胜感激。即使是包含我正在寻找的答案的文档链接,也会非常有帮助。

如果我的解释不清楚,请告诉我,我会提供任何必要的额外信息。

提前致谢。

编辑->

我的最终 CSV 应该与此类似:

Datoer,01/2013,02/2013,03/2013,04/2013,05/2013,06/2013,07/2013,08/2013,09/2013,10/2013
Freespace,800,1000,1243,1387,1457,1562,1620,1700,1800,1900
Allokeret,1000,1200,1456,1689,1784,1865,1930,2000,2100,2200
4

3 回答 3

4

如果我正确理解您的需求,您可以借助 proc transpose 获得所需的结果。

proc transpose data = datain out = dataout;
    var DATO T_ALLOC T_FRESP;
run;

proc export data=dataout
    outfile='xxxxx\tmp.csv'
    dbms=csv
    replace;
run;

SQL的另一个想法。

proc sql noprint;
    select DATO into :dato separated by ',' from datain;
    select T_ALLOC into :talloc separated by ',' from datain;
    select T_FRESP into :tfresp separated by ',' from datain;
quit;

data _NULL_;
    file 'xxxxx\tmp.csv';
    put "var1,&dato";
    put "var2,&talloc";
    put "var3,&tfresp";
run;

还有一个带数组的。

data _NULL_;
    set datain nobs = nobs;
    array data DATO T_ALLOC T_FRESP;
    format t1-t3 $50.;
    retain t1-t3;
    array t[3] $;
    do i = 1 to dim(t);
        if _N_ = 1 then t[i] = put(data[i], 8.);
            else t[i] = compress(t[i] || ',' || put(data[i], 8.));
    end;
    if _N_ = nobs;
    file 'xxxxx\tmp.csv';
    put "var1," t1;
    put "var2," t2;
    put "var3," t3;
run;
于 2013-05-22T13:10:20.810 回答
2

Natsja 的答案是一个很好的答案(只要你所有的值都是数字)。但是由于您询问了数组,所以这里有一个使用数组和传统数据步骤处理的更冗长的答案:

data have;
   input DATO T_ALLOC T_FRESP;
   datalines;
19328      647        1804 
19359      654        1797 
19390      662        1789 
19418      676        1774 
19449      636        1815 
19479      698        1753 
run;

/* Find number of records in data set */
/* The "separated by" clause is a trick to trim leading blanks */
proc sql noprint;
   select count(*) into :num_recs separated by ','
   from have;
quit;

data _null_;
   /* Define variables wanted */
   /* These could be defined as _TEMPORARY_ arrays but I left them as */
   /* creating actual variables for illustration.                     */
   array a(&num_recs) DATO1-DATO&num_recs;
   array b(&num_recs) T_ALLOC1-T_ALLOC&num_recs;
   array c(&num_recs) T_FRESP1-T_FRESP&num_recs;

   /* Load the arrays */
   do while(not eof);
      set have end=eof;
      _i_ + 1;
      a(_i_) = DATO;
      b(_i_) = T_ALLOC;
      c(_i_) = T_FRESP;
      end;

   /* Create the CSV file with three records */
   file 'c:\temp\wanted.csv' dlm=',';

   length header $10;
   header = 'Datoer';
   put header @;
   do _i_ = 1 to dim(a);
      put a(_i_) :mmyys. @;
      end;
   put;
   header = 'Freespace';   
   put header @;
   do _i_ = 1 to dim(b);
      put b(_i_) @;
      end;
   put;
   header = 'Allokeret,';   
   put header @;
   do _i_ = 1 to dim(c);
      put c(_i_) @;
      end;
   put;

   /* Explicitly stop the data step in this example */
   stop;
run;

我已经“增强”了答案,以允许您的起始数据集中有可变数量的行。

此外,您提到在大型机上运行:唯一需要的更改应该是操作系统特定的 FILE 语句。

更新: 根据乔的有用评论修改答案。

于 2013-05-22T13:42:40.183 回答
0

当鲍勃发布他的时,我正要发布这个;无论如何,我会继续发布它,因为它显示了一些与他不同的概念。如果您不想要中间数据集,并且有一个相当大的数据集,那么您最好的选择可能是两者的组合。

data have;
input DATO    T_ALLOC    T_FRESP;
datalines;
19328      647        1804 
19359      654        1797 
19390      662        1789 
19418      676        1774 
19449      636        1815 
19479      698        1753 
;;;;
run;

*Get the array parameter;
proc sql noprint;
select count(1) into :reccount from have ;
quit;

data want;
length varname $8;
*Define the intermediate arrays as _temporary_ so they are stored in memory only;
array datos[&reccount] _temporary_;
array tallocs[&reccount] _temporary_;
array tfresps[&reccount] _temporary_;
*The final array that will be written out is stored in physical disk space;
*If you write this out to a file directly this array can be skipped;
array final_vars[&reccount];

do _t = 1 to &reccount;
 set have;
 datos[_t]=dato;
 tallocs[_t]=t_alloc;
 tfresps[_t]=t_fresp;
end;

*If I were doing this I would write a macro to do this part, as it is the same thing three times;
varname="DATO";
do _t = 1 to &reccount;
 final_vars[_t]=datos[_t];
end;
output;

varname="T_ALLOC";
do _t = 1 to &reccount;
 final_vars[_t]=tallocs[_t];
end;
output;

varname="T_FRESP";
do _t = 1 to &reccount;
 final_vars[_t]=tfresps[_t];
end;
output;

keep final_vars: varname;
run;
于 2013-05-22T13:52:12.620 回答