如何导入分隔符为“;”的 CSV 文件和小数分隔符作为“,”进入SAS?
How to import a CSV file with delimiter as ";" and decimal separator as "," into SAS?
我有(并且将来会收到)许多使用分号作为分隔符和逗号作为小数点分隔符的 CSV 文件。
到目前为止,我无法找到如何使用 proc import 将这些文件导入 SAS,或者以任何其他自动化方式将这些文件导入 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 中看起来像 35,058(意思是三万五千...)(并且在重新- 出口到德国 EXCEL 它看起来像 35.058,00)。
一个简单但肮脏的解决方法如下:
data sap02; set sap01;
AMOUNT = AMOUNT/100;
format AMOUNT best15.2;
run;
我想知道是否有一种简单的方法来定义 CVS 导入的小数点分隔符(类似于分隔符的规范)。 ..或与我的解决方法相比的任何其他 "cleaner" 解决方案。
非常感谢!
从技术上讲,您应该使用 dbms=dlm
而不是 dbms=csv
,尽管它确实可以解决问题。 CSV 表示 "Comma separated values",而 DLM 表示 "delimited",这里是正确的。
我认为没有直接的方法可以让 SAS 通过 PROC IMPORT
以逗号读入。您需要告诉 SAS 在读取数据时使用 NUMXw.d 信息格式,但我看不到在 SAS 中强制执行该设置的方法。 (output 有一个带逗号 NLDECSEPARATOR
的选项,但我认为它在这里不起作用。)
您最好的选择是自己编写数据步骤代码,或者 运行 PROC IMPORT
,转到日志,然后 copy/paste 将代码读入您的程序;然后为每个读入记录添加 :NUMX10.
或任何适当的字段最大宽度。它最终看起来像这样:
data want;
infile "whatever.txt" dlm=';' lrecl=32767 missover;
input
firstnumvar :NUMX10.
secondnumvar :NUMX10.
thirdnumvar :NUMX10.
fourthnumvar :NUMX10.
charvar :.
charvar2 :.
;
run;
还会生成大量的信息格式代码;您可以交替地将信息格式转换为 NUMX10.
而不是 BEST.
,而不是将信息格式添加到读入中。您也可以只删除信息,除非您有日期字段。
data want;
infile "whatever.txt" dlm=';' lrecl=32767 missover;
informat firstnumvar secondnumvar thirdnumvar fourthnumvar NUMX10.;
informat charvar .;
format firstnumvar secondnumvar thirdnumvar fourthnumvar BEST12.;
format charvar .;
input
firstnumvar
secondnumvar
thirdnumvar
fourthnumvar
charvar $
;
run;
Your best bet is either to write data step code yourself, or to run
the PROC IMPORT, go to the log, and copy/paste the read in code into
your program
这有一个缺点。如果 csv 文件的结构发生变化,例如更改列顺序,则必须更改 SAS 程序中的代码。
因此,更改输入更安全,将数字字段中的逗号替换为点并将修改后的输入传递给 SAS。
第一个想法是为此使用 perl 程序,然后在 SAS 中使用带有管道的文件名来读取修改后的输入。
不幸的是,在 proc 导入中存在 SAS 限制:IMPORT 过程不支持 FILENAME 语句的设备类型或访问方法,DISK 除外。
因此必须使用调整后的输入在磁盘上创建一个工作文件。
我使用了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;
我有(并且将来会收到)许多使用分号作为分隔符和逗号作为小数点分隔符的 CSV 文件。 到目前为止,我无法找到如何使用 proc import 将这些文件导入 SAS,或者以任何其他自动化方式将这些文件导入 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 中看起来像 35,058(意思是三万五千...)(并且在重新- 出口到德国 EXCEL 它看起来像 35.058,00)。 一个简单但肮脏的解决方法如下:
data sap02; set sap01;
AMOUNT = AMOUNT/100;
format AMOUNT best15.2;
run;
我想知道是否有一种简单的方法来定义 CVS 导入的小数点分隔符(类似于分隔符的规范)。 ..或与我的解决方法相比的任何其他 "cleaner" 解决方案。 非常感谢!
从技术上讲,您应该使用 dbms=dlm
而不是 dbms=csv
,尽管它确实可以解决问题。 CSV 表示 "Comma separated values",而 DLM 表示 "delimited",这里是正确的。
我认为没有直接的方法可以让 SAS 通过 PROC IMPORT
以逗号读入。您需要告诉 SAS 在读取数据时使用 NUMXw.d 信息格式,但我看不到在 SAS 中强制执行该设置的方法。 (output 有一个带逗号 NLDECSEPARATOR
的选项,但我认为它在这里不起作用。)
您最好的选择是自己编写数据步骤代码,或者 运行 PROC IMPORT
,转到日志,然后 copy/paste 将代码读入您的程序;然后为每个读入记录添加 :NUMX10.
或任何适当的字段最大宽度。它最终看起来像这样:
data want;
infile "whatever.txt" dlm=';' lrecl=32767 missover;
input
firstnumvar :NUMX10.
secondnumvar :NUMX10.
thirdnumvar :NUMX10.
fourthnumvar :NUMX10.
charvar :.
charvar2 :.
;
run;
还会生成大量的信息格式代码;您可以交替地将信息格式转换为 NUMX10.
而不是 BEST.
,而不是将信息格式添加到读入中。您也可以只删除信息,除非您有日期字段。
data want;
infile "whatever.txt" dlm=';' lrecl=32767 missover;
informat firstnumvar secondnumvar thirdnumvar fourthnumvar NUMX10.;
informat charvar .;
format firstnumvar secondnumvar thirdnumvar fourthnumvar BEST12.;
format charvar .;
input
firstnumvar
secondnumvar
thirdnumvar
fourthnumvar
charvar $
;
run;
Your best bet is either to write data step code yourself, or to run the PROC IMPORT, go to the log, and copy/paste the read in code into your program
这有一个缺点。如果 csv 文件的结构发生变化,例如更改列顺序,则必须更改 SAS 程序中的代码。
因此,更改输入更安全,将数字字段中的逗号替换为点并将修改后的输入传递给 SAS。
第一个想法是为此使用 perl 程序,然后在 SAS 中使用带有管道的文件名来读取修改后的输入。
不幸的是,在 proc 导入中存在 SAS 限制:IMPORT 过程不支持 FILENAME 语句的设备类型或访问方法,DISK 除外。
因此必须使用调整后的输入在磁盘上创建一个工作文件。
我使用了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;