高效地将SAS数据集转换为CSV

高效地将SAS数据集转换为CSV,csv,sas,Csv,Sas,谁能告诉我以编程方式将SAS数据集转换为CSV文件的最快方法是什么。我知道我可以使用数据步骤并输出到文件等,但这是唯一的方法吗 谢谢, 阿德南。这是什么 proc export data=sashelp.class outfile='c:\temp\sashelp class.csv' dbms=csv replace; run; 创建SAS数据集的.CSV文件的5种不同方法 请参考这里的答案,这里有许多创建csv的方法,但不一定是这些方法的效率。我创建了一个样本数据集

谁能告诉我以编程方式将SAS数据集转换为CSV文件的最快方法是什么。我知道我可以使用数据步骤并输出到文件等,但这是唯一的方法吗

谢谢,
阿德南。

这是什么

proc export data=sashelp.class
    outfile='c:\temp\sashelp class.csv'
    dbms=csv
    replace;
run;

创建SAS数据集的.CSV文件的5种不同方法


请参考这里的答案,这里有许多创建csv的方法,但不一定是这些方法的效率。我创建了一个样本数据集(
temp
),其中包含100000行和五列,以测试和比较将sas数据集导出到名为
temp.csv
的csv的方法


第一种方法:导出过程。运行时间:0.43秒

PROC EXPORT data=temp 
     outfile="temp.csv" dbms=csv replace;
ODS csv file="temp.csv";
PROC PRINT data=temp noobs;
RUN;
ods csv close;
DATA _null_;
    FILE "temp.csv ";
    SET temp;
    put (_all_) (',');
RUN;
运行时间快,简单,在选择其他选项时具有机箱内的灵活性。尽管如此,它并不是最适合定制的


第二种方法:ODS和打印程序。运行时间:14.09秒

PROC EXPORT data=temp 
     outfile="temp.csv" dbms=csv replace;
ODS csv file="temp.csv";
PROC PRINT data=temp noobs;
RUN;
ods csv close;
DATA _null_;
    FILE "temp.csv ";
    SET temp;
    put (_all_) (',');
RUN;
对于大多数用例,这种方法是三种方法中最差的一种,尽管有一些特殊用例。这对于以前编写的过程的临时输出是很好的,特别是如果您希望输出保持在lst文件中(如果不是太大的话)。当您希望将另一个过程(例如,复杂的
表格
)转换为文件而无需进一步操作时,它也可能很有用。如果您不需要在lst文件中打印输出,请关闭您的列表(
ods listing close
),否则这将花费非常长的时间


第三种方法:文件语句。运行时间:0.06秒

PROC EXPORT data=temp 
     outfile="temp.csv" dbms=csv replace;
ODS csv file="temp.csv";
PROC PRINT data=temp noobs;
RUN;
ods csv close;
DATA _null_;
    FILE "temp.csv ";
    SET temp;
    put (_all_) (',');
RUN;
虽然这种方法的性能还不错,但它不直观,看起来很混乱。但是,如上所述,您可以更好地控制输出,并且它的运行时间是所有输出中最快的。

Modified
data\u NULL
approach 这里是对
data\u NULL\u
方法的修改,该方法在第一个数据步骤中将头行写入文件,然后在第二个数据步骤中继续使用数据行写入同一文件

%macro outputCSV(dataset,file);
data _NULL_;
   file "&file." dlm=',' dsd;
   length header $ 2000;
   dsid=open("&dataset.","i");
   num=attrn(dsid,"nvars");
   do i=1 to num;
      header = trim(left(coalescec(varlabel(dsid,i),varname(dsid,i))));
      put header @;
   end;
   rc=close(dsid);
run;

data _NULL_;
   set &dataset.;
   file "&file." mod dlm=',' dsd;
   put (_all_) (+0);
run;
%mend;

%outputCSV(sashelp.class,~/temp4.csv)
它可以使用
keep
drop
数据集选项(令人惊讶),但不幸的是,当使用
open()
打开数据集时,
nvars
属性尊重
keep
drop
之后的新变量数,但是
varlabel
varname
函数仍然使用它们的
varnum
查找变量

在下面的示例中,仅从
SASHELP.CLASS
中提取
Name
(varnum=1)和
Height
(varnum=4),因为只保留了两个变量,
nvars
是2,但是如果我们在循环中以num作为上限进行迭代,我们会遗漏
Height
,因为它的
varnum
是4:

 62         data _NULL_;
 63           dsid = open("sashelp.class (keep=name height)","i");
 64           num = attrn(dsid,"nvars");
 65           do i=1 to 5;
 66             vname = varname(dsid,i);
 67             put i= vname= num=;
 68           end;
 69         run;
 
 i=1 vname=Name num=2
 NOTE: Argument 2 to function VARNAME(1,2) at line 66 column 13 is invalid.
 i=2 vname=  num=2
 NOTE: Argument 2 to function VARNAME(1,3) at line 66 column 13 is invalid.
 i=3 vname=  num=2
 i=4 vname=Height num=2
 NOTE: Argument 2 to function VARNAME(1,5) at line 66 column 13 is invalid.
 i=5 vname=  num=2
 dsid=1 num=2 i=6 vname=  _ERROR_=1 _N_=1
有两种选择:

  • 通过剥离第一次传递的数据集选项,提取真实的
    nvars
  • 使用一个非常高的数字,而不是
    num
    ,尽管这只会导致日志中出现大量
    “无效”
    注释
这是第一种方法,需要两次调用
open
函数:

%macro outputCSV(dataset,file);
data _NULL_;
   file "&file." dlm=',' dsd;
   length header $ 2000;
   dsid=open("%SCAN(&dataset.,1,()","i");
   num=attrn(dsid,"nvars");
   rc=close(dsid);
   dsid=open("&dataset.","i");
   do i=1 to num;
      header = trim(left(coalescec(varlabel(dsid,i),varname(dsid,i))));
      if _error_ = 0 then put header @;
      _error_ = 0;
   end;
   rc=close(dsid);
run;

data _NULL_;
   set &dataset.;
   file "&file." mod dlm=',' dsd;
   put (_all_) (+0);
run;
%mend;

%outputCSV(sashelp.class (keep=name height),~/temp4.csv)

在写出所有这些之后,在大多数情况下使用
PROC EXPORT
,或者在变量不多的情况下显式列出变量可能是有意义的。这只是说明了可以做些什么。

是的,这是我们讨论过的选项之一。您知道它与数据步骤方法相比是如何伸缩的吗?根据日志,proc export生成一个数据空步骤来写出文本文件。所以我想从一开始就使用数据步骤在cpu时间方面会更有效率。数据步骤可以让您更好地控制输出。我可能最终会使用数据null,因为我想控制导出哪些列,以及格式化/不格式化列值等。仅供参考,我注意到在运行SAS程序(在批处理模式下)时必须使用-noterminal选项使用proc export创建csv或其他平面文件的。您错过了
%ds2csv
宏:警告:data null方法不会在.csv的第一行输出变量名,这可能是个问题。您应该在file语句中使用DSD选项,而不是手动写入分隔符。否则,您可能无法获得可解密的文件。请注意,添加一点代码来编写标题行并不难。@Tom我觉得有另一个答案在路上…?不需要使用那些旧的SCL函数。只需使用PROC TRANSPOSE按顺序创建一个具有变量名的数据集
proc transpose data=have(obs=0)out=name;var u all u;运行然后使用简单的数据步骤写入标题行。然后将MOD选项添加到数据步骤中写入实际数据行的file语句中。是的,很好的调用,尝试使用
array\u character\uu
及其对应项进行类似操作,但无法按顺序显示列。谢谢@mjsqu!这是一个很好的答案-我将您的代码合并到我们的宏库中,我希望这样可以: