通过示例学SAS(1)--从外部文件读入数据
1.设在路径:c:"books"learning下有文本文件mydata.txt,其数据以空格格开,形式如下:
M 50 68 155
F 23 60 101
M 65 72 220
F 35 65 133
M 15 71 166
读入SAS的代码如下:
data demographics;
infile 'c:"books"learning"mydata.txt';
input Gender $ Age Height Weight;
run;
符号$ 表示变量Gender为一字符型变量。为了检查读入文件是否正确,可以通过Print过程察看其观测值。
title "Listing of data set DEMOGRAPHICS";
proc print data=demographics;
run;
若源文件中的数据有缺失值怎么办?比如说mydata.txt的数据内容如下
M 50 68 155
F 60 101
M 65 72 220
F 35 65 133
M 15 71 166
当SAS读到第二行时,会以60代表年龄,101代表身高。接下来会以下一行M代表体重,而M是一字符型变量。叮当,SAS在Log中报错了。正确的方式为,以 . 代表缺失值。如下图
M 50 68 155
F . 60 101
M 65 72 220
F 35 65 133
M 15 71 166
2.读入CSV格式文件。
无需废话,看代码
data demographics;
infile 'c:"books"learning"mydata.csv' dsd;
input Gender $ Age Height Weight;
run;
DSD(delimiter-sensitive data)有几个作用。其一,表明以逗号分隔数据;其二,在一行中若有两个逗号,表明在中间有一个缺失值;其三,若字符型变量置有引号,则可以去掉其引号。上述代码的另一种形式为
filename preston 'c:"books"learning"mydata.csv';
data demographics;
infile preston dsd;
input Gender $ Age Height Weight;
run;
变量demographics是实际文件名字的别名。
如果csv格式文件不是以逗号分隔开,怎么办?例如下述文件以冒号分隔数据
M:50:68:155
F:23:60:101
M:65:72:220
F:35:65:133
M:15:71:166
读入此文件时,使用下述形式
infile 'file-description' dlm=':' ;或者infile 'file-description' delimiter=':';
如果数据是以TAB隔开呢?事情有点麻烦,但还在控制中。此时以十六进制字符代表TAB,例如
对于ASCII文件,infile 'file-description' dlm='09'x;
对于EBCDIC文件,infile 'file-description' dlm='05'x;
3.读入固定列--方式1:列输入
许多数据是以固定列(fixed columns)的形式保存在文件中。读入此种文件可以列输入(column input)的方式读入。这种方法可以读入字符型变量,格式化数字。格式化数字,不仅是正负形式的数据,还有指数形式的数值。比方说3.4E3表示3.4*10^3.
假设有如下形式的数据,保存在bank.txt中。
00110/21/1955M 1145
00211/18/2001F 18722
00305/07/1944M 123.45
00407/25/1945F -12345
没有任何分隔符。怎么办,看代码
data financial;
infile 'c:"books"learning"bank.txt';
input Subj $ 1-3
DOB $ 4-13
Gender $ 14
Balance 15-21;
run;
方式2.格式化输入(Formatted input)
当数据是非标准化形式存放时,就应当考虑格式化输入方法了。还是以上面的例子为例,格式化输入的代码为
data financial;
infile 'c:"books"learning"bank.txt';
input @1 Subj $3.
@4 DOB mmddyy10.
@14 Gender $1.
@15 Balance 7.;
run;
符号@称为列指针(Column Pointer),@4就是告诉SAS,指到第4列。有两种格式化形式,w.d和$w。w告诉SAS有几列数据需要读取,d表示小数点在其值的位置。例如,以3.0形式读入123,SAS会保存为123.0,对同一数字以3.1读入,SAS会保存为12.3.如果需读入的数字本身有小数点,则d将会被忽略。如以4.1的形式读入1.23,SAS仍会保存为1.23.而$w表示将读入w列数据。
需要读入日期数据时,MMDDYY10.告诉SAS以mm/dd//yyyy的形式读入日期,SAS会以1960年1月1日为起始日到此日期的天数保存。所以,如果读入01/01/1960,SAS会保存为0.
执行上述代码后,显示的数据为
Obs Subj DOB Gender Balance
1 001 -1533 M 1145.00
2 002 15297 F 18722.00
3 003 -5717 M 123.45
4 004 -5273 F -12345.00
此时生日均被显示为离1960年1月1日的天数。如果想以常规形式显示,将日期重新进行格式化输出
title "Listing of FINANCIAL";
proc print data=financial;
format DOB mmddyy10.
Balance dollar11.2;
run;
结果显示为
Listing of FINANCIAL
Obs Subj DOB Gender Balance
1 001 10/21/1955 M $1,145.00
2 002 11/18/2001 F $18,722.00
3 003 05/07/1944 M $123.45
4 004 07/25/1945 F $-12,345.00
4.使用Format表达式
假设有一份文件,其数据被空格或逗号隔开,字符长大于8字节。读入时,在Input表达式中紧随变量名后,附上格式形式。中间以冒号隔开。
例如,设有一份CSV文档,其内容如下
"001","Christopher Mullens",11/12/1955,"$45,200"
"002","Michelle Kwo",9/12/1955,"$78,123"
"003","Roger W. McDonald",1/1/1960,"$107,200"
看代码:
data list_example;
infile 'c:"books"learning"list.csv' dsd;
input Subj : $3.
Name : $20.
DOB : mmddyy10.
Salary : dollar8.;
format DOB date9. Salary dollar8.;
run;
另外一种使用Informat表达式的读入数据形式,是显式地使用Informat.上述读入代码可以为
data list_example;
informat Subj $3.
Name $20.
DOB mmddyy10.
Salary dollar8.;
infile 'c:"books"learning"list.csv' dsd;
input Subj
Name
DOB
Salary;
format DOB date9. Salary dollar8.;
run;
如果前述CSV文件中的数据是以空格隔开,且字符没有引号。例如
001 Christopher Mullens 11/12/1955 $45,200
002 Michelle Kwo 9/12/1955 $78,123
003 Roger W. McDonald 1/1/1960 $107,200
问题就来了。名字中的空格会使用SAS以为变量已结束,导致读入不正确。
问题的解决之道在于以&代替冒号:,读入的代码为
data list_example;
infile 'c:"books"learning"list.txt';
input Subj : $3.
Name & $20.
DOB : mmddyy10.
Salary : dollar8.;
format DOB date9. Salary dollar8.;
run;