如何将带分隔符的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导入小数点分隔符(类似于分隔符的规格)。 ..或任何其他“清洁”解决方案相比,我的解决方法。 非常感谢提前!
你应该在技术上使用dbms=dlm
不dbms=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;
谢谢你的帮助,乔!我刚刚编辑过我的帖子,关于dbms选项。你的其他想法很有意思,但仍然是解决方法。很难相信SAS不能处理这样一个普通的问题。但我担心你可能是对的...... – Joz 2015-02-05 15:32:09
SAS可以处理它,乔向你展示了如何。 PROC IMPORT不过是一种在基本文件中读取的实用程序 - 它会写入一个Data Step来读取文件。如果该文件不符合其“基本”的想法,那么您需要编写数据步骤。 – DomPazz 2015-02-05 16:19:15
编辑:很难相信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;
35.358,00,这看起来像一个字符串变量。是35,058,00吗? – 2015-02-05 15:34:12
谢谢,我编辑了我的帖子! – Joz 2015-02-05 16:43:15