如何将分隔符为";",小数分隔符为","的CSV文件导入SAS?



我已经(将来还会收到)许多使用分号作为分隔符、逗号作为小数分隔符的CSV文件。到目前为止,我还不知道如何使用procimport或任何其他自动方式将这些文件导入SAS,而不需要手动处理变量名。

创建一些示例数据:

%let filename = %sysfunc(pathname(work))sap.csv;
data _null_;
  file "&filename";
  put 'a;b';
  put '12345,11;67890,66';
run;

进口代码:

proc import out = sap01 
datafile= "&filename"
dbms = dlm; 
delimiter = ";";
GETNAMES = YES; 
run;

导入后,变量"AMOUNT"的值,如350,58(对应于美国格式中的350.58),在SAS中看起来像35058(意味着三五万…)(再导出到德国EXCEL后,看起来像35.058,00)。一个简单但肮脏的解决方法如下:

data sap02; set sap01;
AMOUNT = AMOUNT/100;
format AMOUNT best15.2;
run;

我想知道是否有一种简单的方法来定义CVS导入的十进制分隔符(类似于分隔符的规范)。。或者与我的变通方法相比任何其他"更清洁"的解决方案。非常感谢!

从技术上讲,应该使用dbms=dlm而不是dbms=csv,尽管它确实能解决问题。CSV表示"逗号分隔的值",而DLM表示"分隔的",这在这里是正确的。

我不认为有一种直接的方法可以通过PROC IMPORT让SAS用逗号读入。你需要告诉SAS在读取数据时使用NUMXw.d信息,我看不出有什么方法可以在SAS中强制设置。(输出有一个选项,用逗号NLDECSEPARATOR,但我认为这在这里不起作用。)

您最好的选择是自己编写数据步骤代码,或者运行PROC IMPORT,转到日志,并将读入的代码复制/粘贴到程序中;然后,对于每个读入的记录,添加:NUMX10.或任何合适的字段最大宽度。它最终会看起来像这样:

data want;
  infile "whatever.txt" dlm=';' lrecl=32767 missover;
  input
    firstnumvar :NUMX10.
    secondnumvar :NUMX10.
    thirdnumvar :NUMX10.
    fourthnumvar :NUMX10.
    charvar :$15.
    charvar2 :$15.
  ;
run;

它还将生成大量的信息和格式代码;您可以交替地将信息转换为NUMX10.而不是BEST.,而不是将信息添加到读入中。您也可以只删除信息,除非您有日期字段。

data want;
  infile "whatever.txt" dlm=';' lrecl=32767 missover;
  informat firstnumvar secondnumvar thirdnumvar fourthnumvar NUMX10.;
  informat charvar $15.;
  format  firstnumvar secondnumvar thirdnumvar fourthnumvar BEST12.;
  format charvar $15.;
  input
    firstnumvar
    secondnumvar
    thirdnumvar
    fourthnumvar
    charvar $
  ;
run;

您的最佳选择是自己编写数据步骤代码,或者运行PROC IMPORT,转到日志,然后将读入的代码复制/粘贴到您的程序

这有一个缺点。如果csv文件的结构发生变化,例如列顺序发生变化,则必须更改SAS程序中的代码
因此,更改输入更安全,在数字字段中用点代替逗号,并将修改后的输入传递给SAS。

第一个想法是使用perl程序,然后在SAS中使用带有管道的文件名来读取修改后的输入
不幸的是,proc import中存在SAS限制:import过程不支持FILENAME语句的设备类型或访问方法,DISK除外
所以必须在磁盘上创建一个具有调整输入的工作文件。

我使用CVS_PP包来读取csv文件
testdata.csv包含要读取的csv数据
replacet_commasep.perl是perl程序的名称

perl代码:

# use lib "/........";    # specifiy, if Text::CSV_PP is locally installed. Otherwise error message: Can't locate Text/CSV_PP.pm in ....;
use Text::CSV_PP;
use strict;
   my $csv = Text::CSV_PP->new({ binary => 1
                                ,sep_char   => ';'
                             }) or die "Error creating CSV object: ".Text::CSV_PP->error_diag ();
   open my $fhi, "<", "$ARGV[0]" or die "Error reading CSV file: $!";
   while ( my $colref = $csv->getline( $fhi) ) {
      foreach (@$colref) {              # analyze each column value
         s/,/./ if /^s*[d,]*s*$/;   # substitute,  if the field contains only numbers and ,
      }
      $csv->print(*STDOUT, $colref);
      print "n";
   }
   $csv->eof or $csv->error_diag();
   close $fhi;

SAS代码:

filename readcsv pipe "perl substitute_commasep.perl testdata.csv";
filename dummy "dummy.csv";
data _null_;
     infile readcsv;
     file dummy;
     input;
     put _infile_;
run;
proc import datafile=dummy
     out=data1
     dbms=dlm
     replace;
     delimiter=';';
     getnames=yes;
     guessingrows=32767;
run;

相关内容

  • 没有找到相关文章

最新更新