全部版块 我的主页
论坛 数据科学与人工智能 数据分析与数据科学 SAS专版
8595 5
2014-11-19

8.input语句与infile语句结合
语法格式
INFILE file-specification <options > <operating-environment-options>;
options
options可以更好地控制打开文件,infile语句的选项有31项之多,这里只选取一些常用实用的予以讲解,更多详细准确的用法请参考帮助文档。
FIRSTOBS=record-number 从指定的行开始读取记录
OBS=record-number 读取到指定的行结束
DELIMITER=delimiters| DLM=delimiters 指定一个字符或多个字符替换空格作为分隔符(对列表方式输入而言),delimiters可以是分隔字符表也可以是分隔变量。
数据中使用不同的字符来分隔数据,将出现的所有单个字符连在一起用引号引起来即构成分隔字符表,例如:
data bp;
    infile datalines delimiter='/,';
    input sbp dbp @@;
    datalines;
120/80, 115/70, 105/75
150/95, 135/85, 100/60
;
也可以先用变量定义分隔字符表,然后在delimiter选项中使用该变量,例如:
d='/,';
infile datalines delimiter=d;

DSD (delimiter-sensitive data)
当数据中含有分隔符时,使用DSD选项将两个相邻的分隔符作为缺失值处理,也就是分隔符敏感的(delimiter-sensitive),而该选项缺省情况下则相邻的分隔符当作一个处理,而且使用DSD选项时候,可以读取引号中含有分隔符的字符串。另外,当分隔符为逗号时,使用DSD时可以省略DLM=选项。例如:
data tpr;
    infile cards dsd delimiter='C';
    input t1-t3;
&nbsp &nbsp cards;
36.9C 37.1C 38.4C
37.2C C 38.1C
;

FLOWOVER/ MISSOVER/ TRUNCOVER/ SCANOVER/ STOPOVER 这5个含有over的选项之所以放在一起,是因为它们都用于读取记录末尾不完整的数据。
FLOWOVER是input默认的读取方式,缺省即是FLOWOVER,当前数据行所含数据个数相比变量个数不够时,SAS会从下一条记录继续读取。很多情况下,原始数据是按照行排好的,不够长度一般代表有部分数据缺失,这时自然不希望继续往下面读下一个数据行,所以就需要后面的这些选项进行处理。
MISSOVER 如果记录行末尾没有足够的数据对应变量或者有不够列宽的数据对应变量,那从当前变量起,到变量列表中最后一个变量都置为缺失值;
TRUNCOVER 跟MISSOVER不同的是如果末端的数据不够列宽则从这里截断,读取的部分数据被保留下来,当前变量之后的变量就会置为缺失值;
SCANOVER 当前记录行找不到@'character-string'表达式指定的字符串时,继续往下面记录行进行查找,一直到找到为止。默认情况或者只有FLOWOVER选项的情况都是与指定SCANOVER等价的,也就是说SCANOVER与MISSOVER, STOPOVER一起使用才是有意义的。
STOPOVER 当前记录行所含数据不够时,停止执行data步,置自动变量_ERROR_为1,将已经读写在数据集的打印出来。如果要创建的数据集已经存在,则中止创建数据集。
虽然解释完了,我想没有实例就空凭文字解释能把这几个over弄明白似乎有点难,而且这几个选项还特容易混淆。
帮助文件上有个例子很不错,但不一定每个人都会去看。
假设有一个文件'c:\over.txt'数据如下
55555
1
22
333
4444
55555
下面分别用上面这些选项读取这个文件
data test;
    infile 'c:\over.txt' *over;
    input testnum 5.;
run;

OBS

FLOWOVER

MISSOVER

TRUNCOVER

STOPOVER

1
2
3
4
5
6

55555
22
4444
55555
.
55555

55555
.
.
.
4444
55555

55555
1
22
333

55555

FLOWOVER与缺省所有*over选项等价,读取记录行第二行时,该行不够5个列宽,则从下一行开始读取,即22,然后下一行数据33不够5个列宽,于是再读取下一行4444;
MISSOVER 第2-4行记录都不够列宽,因此数据丢失;
TRUNCOVER 第2-4行记录都不够列宽,但是数据被保留下来;
STOPOVER 第二条记录不够列宽,所以被停止执行,而且LOG窗口中输出x=. _ERROR_=1 _N_=1。如果数据集test已经存在,则除了在LOG窗口中输出错误信息外不产生任何动作,如果test不存在,则会创建一个test数据集,但是只有已经读取的第一条记录。
现在还有个问题,如果上面一些选项连用会怎么样?
FLOWOVER与MISSOVER或TRUNCOVER连用时,FLOWOVER被屏蔽,相当于没有FLOWOVER;
SCANOVER与MISSOVER或TRUNCOVER连用时,读取@'character-string'定位的数据以SCANOVER为准,而其他数据则以后者为准;
STOPOVER与其他连用则以STOPOVER为准;

N=available-lines
指定输入指针可用的行数

LINE=variable/COLUMN|COL=variable
由用户定义一个变量,SAS会将目前的指针位置存入这个变量中,以便用户使用。类似于自动变量,这里两个变量同样不会被写入数据集中;列变量获得的是当前指针的绝对位置,而行变量则是记录行的相对位置。而指针的位置跟输入方式有关,具体请参看思考题4:读完数据后,指针到哪去了?的解答。

FILENAME=variable/ FILEVAR=variable
FILENAME=variable 由用户指定一个变量,SAS将当前读取的输入文件的完整路径及文件名赋值给这个变量;
FILEVAR=variable 由用户指定一个变量,当infile语句读完当前文件时,接着读取这个变量代表的新文件中的数据。
例如:
data total;
    length fileloc myinfile $ 50;
    input fileloc $ ;
    infile a filevar=fileloc filename=myinfile end=tag;
    do while(not tag);
        input no name $ sex age;
        output;
    end;
    put myinfile ' :Finished reading' ;
    datalines;
x:\project\drug1\center1.txt
x:\project\drug1\center2.txt
x:\project\drug1\center3.txt
x:\project\drug1\center4.txt
;
该程序依次读取center1.txt到center4.txt。感兴趣的可以创建几个外部文件测试一下。
注意:这里infile语句的file-specification只是个占位符,没有实际的意义,既不代表文件标记,也不代表外部文件,但又是必须的。

END=variable/ EOF=label/ EOV=variable
END=variable 由用户定义一个变量,如果当前行是输入文件的最后一行时,该变量被置为1,不是最后一行,则该变量为0。如果使用unbuffered或工作流数据(即cards语句)时,不能使用END=选项;input语句在一次读取一个以上记录行时该选项也无效。例如可以用end=选项在data步一次循环中读完所有的记录:
data end_test;
    infile input1 filename=infile end=tag;
    do until(tag);
        input a b;
        output;
    end;
run;
EOF=label(标号) 由用户指定一个语句标号,当infile语句读到文件末尾时,作为隐含goto语句的目标。如果用input语句读到文件末尾发现剩下的记录行不够则跳过那些记录行到label标号的语句去执行。该选项常用于连续从多个输入文件中读取数据。使用FILENAME=variable选项可以标明数据来源。例如:
data eof_test;
    infile input1 eof=next filename=file1;
    input ……;
    path_file=file1;
    return;
  next:infile input2 eof=last filename=file2;
    input ……;
    path_file=file2;
    return;
  last: infile input3 filename=file3;
    input ……;
    path_file=file3
run;

START=variable
指定一个变量,其值用于指定put _INFILE_语句输出记录的起始变量,例如:
data start_test;
    infile cards start=n;
    n=2;
    input a b;
    put _INFILE_;
    cards;
1 2
3 4
5 6
7 8
;
则程序执行时LOG窗口中只显示b的值,也就是从第二个变量开始输出最近读取的值。具体请参考第六章put语句的讲解。

SHAREBUFFERS|SHAREBUFS
设定file语句和infile语句共享相同的缓冲区,这样可以节省系统资源,加快读写速度,常用于更新外部文件的情况下。
例如:
data _NULL_;
    infile 'x:\test.txt' sharebuffers;
    file 'x:\test.txt' ;
    input @15 birth yymmdd10.;
    age=year(date())-year(birth);
    put age 27-28;
run;

_INFILE_=variable
由用户指定一个字符变量,这个变量存储当前input语句缓冲区中的数据。结合实例理解:
data _infile_test;
    infile cards _infile_=tempchar;
    input name $ birth yymmdd10.; output;
    input name $ birth yymmdd10.; output;
    put tempchar=;
    cards;
WGLO 1965/08/15
FZXU 1954/09/03
;
程序执行完,LOG窗口中输出内容为
tempchar=FZXU 1973/09/03
也就是SAS将当前缓冲区中input语句的整个内容当作一个字符串写入_INFILE_指定的变量,而第一个input语句的在执行到put tempchar=语句时已经不在缓冲区了。

length=variable/ linesize=line-size |LS=line-size
length=variable 由用户指定变量,当input语句开始执行时,将外部文件中记录行的长度写入这个变量。
linesize=line-size 用来限制input语句可以读取的长度,取值范围是10-32767。


二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

全部回复
2016-3-8 08:46:30
你好,我想从左至右一个一个的读取过来,请问像以下这种数据该怎么读取呢,a.txt文件中:
A0007        A0027        A0034        A0063        A0083        A0198        A0213        A0214        A0226        A0303        A0304        A0309        A0311        A0313        A0334        A0335        A0366        A0423        A0495        A0543
A0613        A0617        A0635        A0665        A0687        A0735        A0751        A0755        A0766        A0818        A0898        A0906        A0917        A0928        A0931        A0976        A1019        A1023        A1030        A1050
A1156        A1169        A1179        A1196        A1216        A1257        A1282        A1318        A1421        A1427        A1434        A1441        A1468        A1476        A1521        B0009        B0010        B0012        B0014        B0025
B0027        B0029        B0030        B0049        B0050        B0053        B0059        B0062        B0083        B0084        B0087        B0095        B0096        B0117        B0118        B0136        B0141        B0142        B0144        B0150
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2016-4-25 16:47:31
能解释一下n=,line=和col=么,对指针不怎么懂
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2016-10-31 11:29:20
这个真是精华帖!!!必须赞
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2017-9-17 10:25:26
Setehk 发表于 2016-3-8 08:46
你好,我想从左至右一个一个的读取过来,请问像以下这种数据该怎么读取呢,a.txt文件中:
A0007        A0027        A00 ...
随便定义一个数据集 exercise,变量名为name
按照从左到右的顺序依次读取,代码如下:
data exercise;
    infile '文件的绝对地址/相对地址';
    input name $ @@;
proc print data=exercise;
run;
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2018-2-6 10:33:26
abceddsd 发表于 2017-9-17 10:25
随便定义一个数据集 exercise,变量名为name
按照从左到右的顺序依次读取,代码如下:
data exercise;
C:\Users\zhang\Desktop\a    其中a是txt文件名,那前面属于绝对地址么?
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

相关推荐
栏目导航
热门文章
推荐文章

说点什么

分享

扫码加好友,拉您进群
各岗位、行业、专业交流群