如何将带分隔符的CSV文件导入为“;”和小数点分隔符为“,”到SAS?

问题描述:

I`ve了(和将接受在未来)使用分号作为分隔符和逗号作为小数点分隔符许多CSV文件。 到目前为止,我无法找到如何将这些文件导入SAS使用PROC进口 - 或任何其他自动方式,无需手动与变量名乱搞。如何将带分隔符的CSV文件导入为“;”和小数点分隔符为“,”到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; 

导入为变量“量”如350,58(一个值,其对应于350.58在后美国格式)在SAS中看起来像35,058(意思是三十五万...)并且在再出口到德国EXCEL之后,它看起来像35.058,00)。 一个简单而肮脏的解决方法是以下几点:

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

我不知道是否有一个简单的方法来定义的CVS导入小数点分隔符(类似于分隔符的规格)。 ..或任何其他“清洁”解决方案相比,我的解决方法。 非常感谢提前!

+0

35.358,00,这看起来像一个字符串变量。是35,058,00吗? – 2015-02-05 15:34:12

+0

谢谢,我编辑了我的帖子! – Joz 2015-02-05 16:43:15

你应该在技术上使用dbms=dlmdbms=csv,尽管它理出头绪。 CSV意味着“逗号分隔值”,而DLM意味着“分隔”,这在这里是正确的。

我不认为有一个直接的方式,使SAS通过PROC IMPORT用逗号读入。你需要告诉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; 

它也会生成大量的信息和格式代码;您可以将informats交替转换为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; 
+0

谢谢你的帮助,乔!我刚刚编辑过我的帖子,关于dbms选项。你的其他想法很有意思,但仍然是解决方法。很难相信SAS不能处理这样一个普通的问题。但我担心你可能是对的...... – Joz 2015-02-05 15:32:09

+0

SAS可以处理它,乔向你展示了如何。 PROC IMPORT不过是一种在基本文件中读取的实用程序 - 它会写入一个Data Step来读取文件。如果该文件不符合其“基本”的想法,那么您需要编写数据步骤。 – DomPazz 2015-02-05 16:19:15

+0

编辑:很难相信SAS不能自动处理这样一个世俗的问题。但我目前正在与乔的解决方案合作,再次感谢! – Joz 2015-02-05 16:28:56

您最好的选择是要么自己写数据的步骤的代码,或运行 的PROC IMPORT,转到日志和复制/代码读取粘贴到 程序

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

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

我使用CVS_PP包来读取csv文件。
testdata.csv包含要读取的csv数据。
substitute_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;