SAS CSV 导入添加垃圾数据列

SAS CSV import adds junk data column

我正在尝试将数据导入 SAS Enterprise Guide。该文件是一个 csv,最初是通过在 Mac 上保存 Excel 文档生成的。共有三列,Date、DayOfYear 和 MonthOfYear。

我的导入代码如下所示:

DATA indata;
    INFILE '/sasdata/{path_to_file}' TERMSTR=cr DSD DLM=',';
    INPUT Date YYMMDD10. DayOfYear MonthOfYear;
    FORMAT Date YYMMDD10.;
RUN;

问题在于,这会导致日期列之后的所有内容都被移动一列。示例输出:

Date       | DOY | MOY
2017-01-01 |     |  1
2017-01-02 |     |  2
2017-01-03 |     |  3

我的 hacky 解决方案是添加一个名为 junk 的额外列以获取所有空值,但如果可能的话我想真正解决这个问题。在下面破解。

DATA indata;
    INFILE '/sasdata/{path_to_file}' TERMSTR=cr DSD DLM=',';
    INPUT Date YYMMDD10. junk DayOfYear MonthOfYear;
    FORMAT Date YYMMDD10.;
RUN;

Date       | junk | DOY | MOY
2017-01-01 |      |  1  |  1
2017-01-02 |      |  2  |  1
2017-01-03 |      |  3  |  1

我试过弄乱换行和回车 returns 但无济于事。我同时输入了 DSD 和 DLM,但这并没有改变任何东西。日期的末尾似乎有一个额外的不可见字符,该字符在它自己的列中结束,但是当我在十六进制编辑器中查看数据时,那里什么也没有。例如

ef bb bf 32-30 31 37 2d-30 31 2d 30-31 2c 31 ...

它直接从 2017-01-01 到逗号到 1。所以没有隐藏字符。我不确定这还会发生什么。这是我遇到此问题的第二个文件,所以我知道这不仅仅是一次性的事情。

总结一下我的问题,如何避免为日期变量后的垃圾创建额外的列?

您应该在输入语句中使用冒号 (:) 来应用信息格式,如下所示:

DATA indata;
    INFILE '/sasdata/{path_to_file}' TERMSTR=cr DSD DLM=',';
    INPUT Date : YYMMDD10. DayOfYear MonthOfYear;
    FORMAT Date YYMMDD10.;
RUN;

根据documentation

The : (colon) format modifier enables you to use list input but also to specify an informat after a variable name, whether character or numeric. SAS reads until it encounters a blank column, the defined length of the variable (character only), or the end of the data line, whichever comes first.

如果您正在读取分隔数据,那么您应该使用列表模式输入。您可以从 INPUT 语句中删除所有信息格式,或者在 INPUT 语句中的信息格式之前添加 : 修饰符,以便您仍然使用修改后的列表模式。如果从输入语句中删除信息格式,则可以使用 INFORMAT 语句告诉 SAS 如何读取日期变量。

data indata;
  infile '/sasdata/{path_to_file}' termstr=cr dsd truncover ;
  length Date DayOfYear MonthOfYear 8;
  input Date DayOfYear MonthOfYear;
  informat date yymmdd. ;
  format Date yymmdd10.;
run;

当您告诉 SAS 在读取带分隔符的数据行时使用格式化输入时,可能会发生三种情况,所有这些都是不好的。

(1) 您可能读取的字符太少,因此得到错误的结果。这也会导致日期值的其余部分被读取为下一列的值。

(2) 读取的字符过多,因此请尝试读取下一个定界符作为日期的一部分,甚至是下一个值的一部分。并且可能只留下下一个值的一部分以供下一列读取。

(3) 准确读取正确数量的字符,使日期正确,但随后将光标位置留在下一个分隔符之前。然后,如果您使用 DSD 选项允许空值,这将使 SAS 认为下一个值为空,并且基本上将所有其余行移到错误的列中。