SAS flowover truncover scanover pad missover选项(2)
以下来自终于总结了一下,truncover, missover, pad选项的意义,以及读取datalines和外部文件 - SAS专版 - 经管之家(原人大经济论坛) (pinggu.org)
因为对sas inputinfile 读取cards数据和外部文件,如txt, dat数据诸多的疑惑,以及对infile选项 truncover, missover, flowover,pad, lrecl等选项的一知半解。前些日子特地在论坛上提了两个问题:
input读入原始数据,datalines和txt中的区别?
https://bbs.pinggu.org/forum.php?mod=viewthread&tid=1571120&from^^uid=3269938
关于input输入原始数据
https://bbs.pinggu.org/forum.php?mod=viewthread&tid=2145400&from^^uid=3269938
请教了论坛的各位大牛,有davil2000,webgu, ziyenano, pobel等等,他们都给出了很好的解释和回答,但总体还是没有一个系统的解答,因此我在总结了各位大牛的回答的基础上,查阅了相关文献,有了一个初步的理解,写出来与大家分享,也希望各位大牛能补充说明。
首先说明,sas的input和infile语句无比强大,可以通过各种输入方式和各种选项实现任何有规律无规律数据的导入,光input, infile的功能我觉得都可以写成一本书了,因此本文不致力于详细讲解input和infile,事实上很多选项我也不懂,但是可以查阅一下sas help在自己需要的时候使用。本文主要对infile中容易误解的几个选项missover, truncover, pad以及input 列表输入和列输入的不同进行说明。
关于input的columninput (列输入)和listinput (列表输入).
简单来说:列输入就是严格按照变量指定的长度进行数据读取,忽略分隔符。如input name 1−10;�����ℎ���40.; 都属于列输入。列表输入就是根据规定的分隔符(默认是空格)按照变量的顺序读取数据,多个空格按照一个处理,遇到空格即停止。如input name ℎ���:40. ;
假设有如下原始数据:
需要注意的是,在windows和unix中的文本处理器如写字板创建上面的数据,数据每行属于可变长度,每行的长度就是灰色区域的长度,而在sas的datalines中,上述的数据是固定长度的,长度为80 bytes,后面没数据的地方以空格填充,在大型主机的某些数据文件中,数据行也是固定长度的,无数据的地方以空格填充。
首先分别以input的列输入和列表输入导入上述数据,假设数据位于d盘infile文件夹中,名字为emplist。
DATA test1; /*column input*/
INFILE "d:\infile\emplist.dat";
INPUT lastn $1-21 Firstn $ 22-31
Empid $32-36 Jobcode $37-45;
RUN;
DATA test2; /*list input*/
INFILE "d:\infile\emplist.dat";
INPUT lastn ������
Empid ������� ;
RUN;
上述程序提交后,结果如何,在此之前,先讲一下flowover选项。Infile默认是flowover选项。
在列输入时:如果input指针到了一行的最后一个字符时,有些变量还是没有得到值或者完整的值,指针就会跳到下一行的第一列开始读取数据,来填充没有值的变量。当下次input语句执行的时候,新的一行数据就会进入inputbuffer。
因此列输入数据如下:
说明,对于第二行数据,pilot没有达到jobcode所需要的长度,因此指针跳到下一行读取smith填补上来。完成之后进入数据步的下一个循环,执行下一次input,因此指针再次跳行,将leistner读入。而读取第五行tomas数据时,harald长度不够firstn用,所以指针跳到下一行将wade读入作为firstn,然后e1026作为empid,pilot仍然不够用,所以跳到下一行读取waugh作为jobcode;
在列表输入时,以空格为分隔符,数据可以正确地读入,但默认的flowover选项仍然会导致将下一行数据读入填充缺失值。结果如下:
使用missover选项:
当在infile语句中使用missover选项时,它会抑制掉flowover,使得在读取短的数据行时,input指针不会跳到下一行来读取数据,相反,它使得没有数据的变量变缺失。
在列输入中加上missover选项时,结果如下:
我们发现的是,再也没有从下一行读取数据,可是jobcode的pilot和第6行的后面仍然没有正确读入。这是因为在列输入的时候,如果指针到了一行的结尾,仍然没能读入满足变量长度的数值,就会将该变量变缺失。解决方法:可以再加入pad选项,pad选项数据后面填上空格,使得每行的长度相同,默认lrecl=256。
如果列表输入infile加上missover选项,结果如下,不会像列输入那样将最后的变量变缺失。
Truncover: 其实truncover的功能类似于missover 和pad合用的效果,它是针对列输入时,如果一行最后读入的数值仍然不能满足变量需要的长度,不会将变量缺失,而是将读入的值赋给该变量。列输入加truncover的结果同上。
当然,对于列表输入,truncover的结果也同上,是正确的结果。
关于PAD,pad固名思义,意思是将数据行的后面部分填上空格,这样就使得数据行变长,不致于让input指针在读取短数据行时到达数据行结尾从而跳行。Pad不会抑制flowover的作用,它会将数据后面的空白位置填上空格,空格的长度由lrecl=n决定,默认n为256,当然可以在infile选项中修改n的大小。这就是为什么在列输入中用missover和pad可以正确读取数据了,因为数据行的长度不再是数据实际的长度(可变长度),而是一个固定长度256,后面都是空格。
如果列表输入只加pad,不加missover,结果如下
Pad不会抑制flowover,并且将多个空格作为一个处理,所以出现了上述结果。
关于读取外部文件和datalines中的区别,很多朋友都发现sas读取外部文件和datalines数据,数据结构完全一样,同样的程序,结果不同。
原因是:外部文件数据,数据行是可变长度,如上例。除非加上pad,以空格填充。
而在cards中的数据,看起来也是可变长度,但其实是固定长度,为80。结尾没有数据的地方都以空格填充。即默认有pad 。引用davil2000大神的回答:
Cardimagesystem option specifies that SAS source and data lines be processed as if thesewere punched card images—all exactly 80 bytes long and padded with blanks.
所以如下两个程序:
data test3;
input lastn $1-21Firstn $ 22-31
Empid $32-36 Jobcode $37-45;
cards;
LANGKAMM SARAH E0045 Mechanic
TORRES JAN E0029 Pilot
SMITH MICHAEL E0065
LEISTNER COLIN E0116 Mechanic
TOMAS HARALD
WADE KIRSTEN E0126 Pilot
WAUGH TIM E0204 Pilot
;
run;
data test4;
input lastn ������
Empid ������� ;
cards;
LANGKAMM SARAH E0045 Mechanic
TORRES JAN E0029 Pilot
SMITH MICHAEL E0065
LEISTNER COLIN E0116 Mechanic
TOMAS HARALD
WADE KIRSTEN E0126 Pilot
WAUGH TIM E0204 Pilot
;
run;
本文来自博客园,作者:Iving,转载请注明原文链接:https://www.cnblogs.com/SAS-T/p/17231917.html