3.4 读取PC数据文件
对于单机数据文件的读取,除了LIBNAME语句、SQL直通设施和ACCESS/DBLOAD过程三种方式外,还可以通过IMPORT过程导入。
常见的各种统计软件的数据文件如SPSS的.sav文件、Stata的.dta文件、JMP的.jmp文件,以及Excel文件均可以通过IMPORT过程导入。当然,LIBNAME语句也是不错的选择。
→3.4.1 小试牛刀
比如,我们手头要导入D盘的一个SPSS文件(.sav文件),我们可以分别尝试用IMPORT过程和LIBNAME语句。
程序3-2 导入SPSS文件
*==IMPORT过程; proc importout=mysasdata datafile="D:\01 SAS编程演义\02 Data\Raw\myspssdata.sav" ; run; *==LIBNAME语句; libname mysav spss "D:\01 SAS编程演义\02 Data\Raw\myspssdata.sav";
对于像SPSS这种规范格式的数据文件,这是最简便省事的一个写法。但是如果希望做更丰富更详细的设置,或者是对于一些不太规则的数据文件,我们就有必要去深挖一下PROC IMPORT这个过程以及LIBNAME语句访问PC文件的语法。
→3.4.2 PROC IMPORT语法
我们以官方的Help为基础,加以改造打扮后呈现给各位。结合前面对SAS Help风格的介绍,我们可以比较直观的了解一个过程更为系统、深入的用法。
以语法3-2为例,我们再复习一下:大写粗体的为SAS过程和语句名,如PROC IMORT、DATAFILE以及RUN;大写非粗体的是需要我们原样照抄的参数,如DBMS、OUT以及REPLACE;小写斜体的是需要我们填写指定的参数或者参数值,如filename就是需要我们自己填写的要读入的文件;| 表示我们只能选择其中的一个参数或参数值,因此DATAFILE和DATATABLE我们只能选一个;<>表示我们可用可不用的参数,因此,从语法3-2可以看出一个PROC IMORT过程只有DATAFILE或DATATABLE是必需的。
例如,程序3-2导入SPSS文件时,我们并未指定DBMS=SAV,这是因为SAS导入外部文件时,会依据其扩展名自动猜测其DBMS的值,此外,我们指定了OUT=mysasdata,这样我们自己给生成的SAS数据集起了一个名字叫mysasdata,方便我们自己查找辨认。
PROC IMPORT过程的语法看起来比较复杂,大家不要一开始就害怕。先熟悉必需的、最基本的语法,以后慢慢增加控制选项。下面对卡片中提及的重要参数做一些补充说明:
语法3-2 PROC IMPORT语法参考卡片
● 指定欲读入的文件时,除了完整路径和名称,还可以用此前FILENAME语句给文件指定的快捷方式。例如,如果此前用filename myxls"d:\mydata.xls"指定过mydata. xls的快捷方式名为myxls,则在PROC IMPORT中可直接写为:datafile=myxls。OUT= 指定存放的逻辑库和数据集。有的读者会觉得别扭:明明是读入,为什么不是IN却是OUT呢?如果了解到这里的OUT其实是指把读入到PDV里的数据输出到数据集就不会感到别扭了。
● 对于数据集选项,我们可以用PW=选项加密数据集,或者用READ=、WRITE=、ALTER= 选项分别加密读,写以及修改权限;我们也可以用KEEP=、DROP=、RENAME= 选项筛选,重命名变量;我们还可以用OBS= 和WHERE= 筛选保留的观测。
● 通常情况下,SAS会依据数据文件的扩展名如.CSV、.SAV、.XLS、.DTA等自动匹配相应的DBMS参数,因此不指定DBMS也是可以的,但是不推荐这样做。
● 文件格式说明语句给我们对各种文件的读取提供了更多的控制语句,比如:
■ 对于分隔符分隔的文件,我们可以用DATAROW=n指定数据从第n行开始,用GETNAMES=YES|NO来应对数据文件首行是不是变量名,用GUESSINGROWS=n | MAX来应对仅用默认头20行数据无法准确判断变量类型和长度的情况。此外,我们还可以用DELIMITER='char' | 'nn'x来个性化指定数据文件的分隔符,比如DELIMITER='#'可以读入#分隔的数据文件,DELIMITER='20'x则可以读入空格分隔的数据文件。其中'20' x是用二进制表示空格的ASCII码。
■ 对于大众更熟悉的EXCEL文件,SAS提供了更多的控制语句。最常用的是用SHEET=读入EXCEL文件中某特定的sheet,甚至可用RANGE=来读入某sheet中特定的数据区域。
■ 对于SPSS、Stata数据文件,也有相应的控制语句。具体读者可查看SAS Help。
→3.4.3 LIBNAME访问PC文件语法
当然,除了IMPORT,LIBNAME语句也可做一些更为精细的设置来访问PC数据文件,具体可参考语法3-3。
语法3-3 LIBNAME语句访问PC文件语法参考卡片
不过LIBNAME语句读入PC数据文件这种方式笔者个人不做推荐,这主要是因为:
(1)并非所有的PC数据文件都有相应的引擎支持。
(2)和PROC IMPORT相比,控制选项较少。
→3.4.4 实例扩展
所谓“纸上得来终觉浅,绝知此事要躬行”,结合前面的Help和解析,我们自己动手试试下面的案例。读入EXCEL文件class.xlsx。这是一个很规整的文件,按表3-1数据读取策略总结提供的思路,我们可以用PROC IMPORT进行读入。
程序3-3 读入规整的EXCEL文件
*===读入EXCEL文件; filename myexcel "D:\03 Writting\01 SAS编程演义\02 Data\Raw\class.xlsx"; proc importout=myxls datafile=myexcel dbms=excel replace; run;
有的时候,我们的EXCEL文件不是那么规整,需要我们在读入时做更多的控制和设置,比如我只希望读入特定SHEET的特定区域的数据,这时我们就可以用RANGE、DBDSOPTS等进行设置。在用RANGE进行范围设定时,需要留意,范围名要采用literate name命名法,即把范围放在引号里,且引号后跟n,如Sheet1的A1-E20的命名为:'sheet1$A1:E20'n,或者直接用"sheet1$A1:E20"。
程序3-4 读入特定区域数据的EXCEL文件
*===读入指定范围的EXCEL文件; proc importout=myxls datafile=myexcel dbms=excel replace; range='sheet1$A1:E20'n; /*读入sheet1的A1~E20区域的数据*/ getnames=yes; /*或者rang="sheet1$A1:E20"*/ run; *===读入指定起止行; proc importout=myxls datafile=myexcel dbms=excel replace; dbdsopts="firstobs=3 obs=18"; /*读入sheet1的3~18行区域的数据 */ getnames=yes; run;
EXCEL本身不是数据库管理软件,所以每一列其实并没有固定的数据类型格式(数字/字符),SAS在读入EXCEL文件时,默认用前8行数据判定列的数据类型和长度。如果一个文件的某一列的前8行全部为数字,那么SAS会将这一列作为数字变量读入,但是如果在后面发现文本字符,导致数据类型不一致,而且无法转换成数字,这时就会出现错误。解决的办法就是需要让SAS读入更多的数据行再确定数据类型,可惜针对EXCEL文件,SAS没有直接提供这样的选项,不过我们可以通过修改Windows注册表的EXCEL的TypeGuessRows项的值为0,这样SAS会在读入所有行后再确定变量的类型。
其他PC格式数据文件的读入,同我们上面举的例子类似,读者可参考语法卡片进行尝试,本章不再一一赘述。