【问题标题】:How to import a CSV file with delimiter as ";" and decimal separator as "," into SAS?如何导入分隔符为“;”的 CSV 文件和小数点分隔符为“,”到SAS?
【发布时间】:2015-04-05 12:11:38
【问题描述】:

我已经(并且将来会收到)许多使用分号作为分隔符和逗号作为小数分隔符的 CSV 文件。 到目前为止,我无法找到如何使用 proc import 或以任何其他自动化方式将这些文件导入 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-import 定义小数分隔符(类似于分隔符的规范)。 ..或与我的解决方法相比的任何其他“更清洁”的解决方案。 非常感谢!

【问题讨论】:

  • 35.358,00,这看起来像一个字符串变量。是 35,058,00 吗?
  • 谢谢,我已经编辑了我的帖子!

标签: csv sas decimalformat


【解决方案1】:

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

我认为没有直接的方法可以让 SAS 通过PROC IMPORT 用逗号读入。您需要告诉 SAS 在读取数据时使用NUMXw.d 信息,我看不到在 SAS 中强制执行该设置的方法。 (output 有一个选项,带有逗号,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;

【讨论】:

  • 感谢您的帮助,乔!我刚刚编辑了我的帖子 wrt dbms 选项。您的其他想法很有趣,但仍然是解决方法。很难相信 SAS 无法处理如此平凡的问题。但我担心你可能是对的......
  • SAS 可以处理它,Joe 向您展示了如何。 PROC IMPORT 只不过是一个读取基本文件的实用程序——它编写了一个数据步骤来读取文件。如果文件不符合其“基本”的概念,那么您需要编写数据步骤。
  • 编辑:很难相信 SAS 无法以自动化方式处理如此平凡的问题。但我目前正在使用 Joe 的解决方案,再次非常感谢!
  • PROC IMPORT 用于分隔文件的功能集非常有限。数据步骤输入是您在很大程度上被期望用于任何远程复杂的东西。这不是“解决方法”,就我而言,它是自动化的(并且是可自动化的)。我同意 SAS 没有选项允许它考虑小数点分隔符 '' 有点令人惊讶,但我不确定这在该领域有多普遍。
  • 我认为这仅仅是因为没有足够的需求存在 - 无论如何都有容易完成的方法(包括自动方法)。 SAS 非常擅长在需要时添加新功能 - 您可以 recommend a new feature 并让其他人对其进行投票,而获得高票的通常会实施。当然,它不是开源的,所以你不会获得那么多的功能,但它们非常好。
【解决方案2】:

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

这有一个缺点。如果 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;

【讨论】:

    猜你喜欢
    • 2021-11-19
    • 1970-01-01
    • 2017-06-23
    • 1970-01-01
    • 1970-01-01
    • 2014-02-26
    • 2015-08-09
    • 2019-06-09
    • 1970-01-01
    相关资源
    最近更新 更多