第2章SAS 82编程入门Word格式.docx
《第2章SAS 82编程入门Word格式.docx》由会员分享,可在线阅读,更多相关《第2章SAS 82编程入门Word格式.docx(18页珍藏版)》请在冰豆网上搜索。
a.case2_l;
inputx@@;
cards;
proc
print;
varx;
run;
这一程序仍然可以运行出正确的结果,但显然非常难以阅读。
为了使得程序能够被大多数人方便地阅读,笔者建议初学者遵循以下书写规则:
>除非特别长的语句,每个语句尽量只占一行。
如必须要占多行,从第二行起使用缩进格式以突出语句结构。
>所有的数据步和过程步均主动加上“run;
”语句作为结束。
其第一个语句和最后的RUN语句由第一列开始书写,其他语句按程序的逻辑结构层次遵循缩进格式书写,以使得程序结构更为清晰。
>尽量只使用小写字母,或者关键字使用大写字母,其余部分使用小写字母。
>在较长的程序段前后加上空行、注释语句等以突出分段。
当然,以上规则并非一定要严格遵守,在对SAS程序熟练使用后,也可根据具体情况加以变通。
比如在非常长的程序中,对于一个较短的过程步,可以考虑将全部语句写在同一行,以压缩程序长度,凸现主要的程序段。
2.1.4SAS程序的运行
在程序书写完毕后,就可以提交系统执行了。
SAS程序的调用方式有很多种,最基本的方式为选择菜单run→submit,系统就会依次提交全部语句给系统执行,并在LOG窗口中给出执行信息,在output窗口中列出分析结果。
熟练的用户也可以直接按下F8键,或者单击按钮“
”,作用相同。
如果选中某一段程序,然后进行调用,则系统只执行被选择的部分。
如在示例中如果选中第一行并按“F8”,则只有第一句被提交运行。
该功能在调试程序时非常有用。
2.1.5SAS程序中的注释
为了使得长程序更为清晰易读,在相应程序段问可以考虑使用空行分隔,也可以使用注释加以说明。
SAS中的注释方式共有两种格式:
>注释语句:
使用星号”*”开始,可占多行,以分号“;
”作为结束。
>注释段落:
用字符组“/*”和”*/”,包括起来的任何字符内容,可占多行。
例如以下均为合法的注释内容。
*本句为注释语句示例;
/*此处为注释段落示例*/
*注意:
本注释语句占
了两行,且和星号问无空格,但仍然是正确的;
/*此处的注释段落
示例也占了两行*/
以上两种方式可以根据情况自由选用。
2.2SAS程序的数据步
SAS程序中数据步的作用就是实现对数据的操作,包括数据建立、数据访问、数据编辑和数据文件管理,显然,数据步在SAS程序中起着非常重要的作用。
本节将介绍数据步的基本语法格式,其进一步的功能实现将在下一章讲述。
但是,在讲述数据步的语法之前,我们需要首先了解SAS程序对数据文件的调用方式。
2.2.1逻辑库和逻辑文件名
上一章已经提到,SAS系统将所使用的文件以库的形式组织起来。
在SAS程序中不能直接调用数据文件,只有将其指定为某个库中的文件后,该数据才能以数据集的形式被直接调用。
在PC系统中,SAS数据库与某一个文件夹相对应,我们要为每一个数据库指定一个库标记(库名)来识别该库,上文提到的Libnane命令就用于指定库标记。
其一般格式如下:
Libname库标记‘文件夹位置’选项;
例如要指定目录”C:
\”为库标记A,可以在视窗中提交加下语句:
1ibnamea‘c:
\’;
这一语句就是上面示例程序的第一句。
在运行该语句后,LOG窗口显示如下:
1libnamea'
NOTE:
LibrefAwassuccessfullyassignedasfollows:
Engine:
V8
PhysicalName:
c:
\
这表明库名称A已经被指定给文件夹”C:
\”,此后存储在叫目录下的所有SAS文件都可以在程序中作为A库中的文件被调用。
在调用时每一个数据集都需要使用两级名称来指定,第一级是库标记,第二级是数据集名,中间用“.”隔开,在程序中通过指定两级名来识别文件。
文件两级名的一般形式如下:
库标记.数据集名
如数据文件“c:
\abc.sas7bdat”在上面的libname语句运行完毕后,就可以在程序中使用“a.abc”这一名称来使用。
2.2.2数据步的基本结构
数据步均以DATA语句开始,用于创建和处理数据集。
其中最常用的语句有:
1.DATA语句
它用于标志数据步的开始,同时命名将要创建的SAS数据集。
DATA语句使用时的一般形式如下:
DATA数据集名;
下面是几个data语句的例子。
Datawork..abc;
dataabc;
datasasuser.abc;
dataa.abc;
2.INPUT语句
它的主要功能是确定变量的读入模式,即数据域中的数据都对应了哪些变量。
INPUT语句的格式如下:
INPUT变量名<变量类型起止列数>…;
方括号表示其中的内容为可选,如果不输入,系统会以默认值代替。
以下是几个例子:
inputxyz;
inputxl-xl0;
inputx$y@@;
其中第2句使用了缩写符号,第三句中的$指明变量x为字符变量,@@表明数据是连续读入的,这将在下一章中详细讲解。
3.CARDS/DATALINES语句和数据块
cards语句或datalines语句的功能相同,只是前者适用于任何版本,而后者只在8.0以后的版本中才能使用。
它们均可用于标志数据块的开始,随后紧跟着需要读入的数据,具体格式如下:
CARDS;
Datdines;
数据块数据块
;
需要注意的是数据块必须单独占一行或多行,最后表示数据块结束的分号也必须另起一行书写,否则系统会报错。
前面的简单示例中就使用了cards语句读入数据。
由于分号是作为语句结束符,如果需要读入的数据块中含有分号,则可以使用cards4或者datalines4语句进行数据块定义。
该语句的特点是可以将数据块中的分号正确识别,数据块的结束则用四个连续的分号加以指定,如下例:
datatemp;
inputvarx$varyvarz;
datalines4;
24;
77195177
31220213
56173166
12135125
4.INFILE语句
它的主要功能是指定一个包含原始数据的外部文本文件,从而使得数据步可以从这一文本文件读入数据块。
在数据步中它必须在input语句之前出现,其语法格式如下:
INFILE‘外部文件的所在位置及名称’选项;
注意在数据步中CARDS语句和INFILE语句都是用于指定数据块内容的,它们分别对应了两种数据输入的方式:
直接输入方式和外部文件读入方式。
这将在下一章中讲解,示例中采用的是直接输入方式,运行完毕后LOG窗口的输出如下:
2dataa.1x1;
3inputx@@;
4cards;
NOTE:
SASwenttoanewlinewhenINPUTstatementreachedpasttheendofaline.
ThedatasetA.LX1has6observationsand1variables.
DATAstatementused:
realtime0.01seconds
cputime0.01seconds
6;
输出表明数据集a.1x1已被成功地建立,它含有一个变量(显然是x),6条记录,对应原
始的数据块,读者可以很容易地明白该数据集的具体格式。
5.OUTPUT语句
在默认情况下,数据步将所读入的数据存放在缓存中,在依次执行完全部语句后才将相应信息写成一条新的纪录。
这在许多时候已可以满足基本的数据管理需要,但是,如果使用者希望能在一个执行周期中生成多条数据记录,则需要使用output语句强制输出一条新记录,详见下一章。
6.SET语句
该语句的功能是将指定数据集的内容完整地复制到新建的数据集中,当从头新建SAS数据集时并不需要使用set语句。
但如果想在原有数据集基础上进行数据编辑,则set语句将会非常有用,详见下一章。
2.3SAS程序的过程步
通俗地讲,SAS程序的过程步就是已经编好了的用于实现各种统计分析功能的计算机程序,我们只需要按照规定好的格式调用它们就是了。
程序步总是用一个PROC语句开始,后面紧跟着过程步名,用以区分不同的过程步。
表2.1是一些常用过程步的名称及功能。
表2.1SAS中常用的程序步
程序步名功能
SORT将指定的数据集按指定变量排序
PRINT将数据集中的数据列表输出
GCHART绘出高分辨率的统计图
UNIVARIATE对指定的数值变量进行详细的统计描述
MEANS对指定的数值变量进行简单的统计描述
freq对指定的分类变量进行统计描述和检验
NPAR1WAY进行非参数检验
TTEST进行两样本t检验
ANOVA进行多变量方差分析
GLM拟合一般线性模型
REG拟合多重线性回归模型
CORR进行指定变量间的相关分析
LOGISTIC拟合logistic回归模型
PHREG拟合COX比例风险模型
2.3.1过程步的基本结构
由表2.1可见,SAS的许多统计分析功能都是通过过程步来体现的,可如此多的种类也使我们难以总结出一个程序步的公式来。
不过仍可给出大致的语法结构如下:
PROC过程名<DATA=数据集名><选项>;
该过程的专用语句描述<相关语句选项>;
<VAR变量序列>
<WHERE记录选择条件表达式…;
>
<By变量序列>
Run;
尖括号里的语句或选项均可以省略,此时该过程按最通常的情况来处理,即:
>处理最新建立的SAS数据集。
>处理所有的变量(或对一个计算过程来说处理全部数值变量)。
>一次处理整个数据集而不是某个子集。
我们在示例中用到的PRINT过程步中,相应的数据集就是采用的这种默认方式,而所需处理的变量则进行了指定,事实上,在本例中var语句完全可以省略,执行结果相同。
需要注意的是,过程本身和许多过程中的语句均可使用选项,以实现更复杂的分析功能。
但是不同的语句其选项的设置方式有所区别,过程本身的选项一般直接跟在过程名后即可,中间无需使用斜杠“/”分隔,许多语句,如output语句的选项也不需要分隔,但是在某些语句,如model语句中,选项和语句主干之间则必须使用“/”分隔,这一点初学者非常容易混淆。
请读者在使用时一定要注意相应过程步的语法约定。
2.3.2过程步的语法说明
但在更多阶情况下,我们的要求超出了默认方式所提供的范围,这时就要动用方括号里的
秘密武器了。
下面我们依次介绍在过程步中常见的语句和选项。
1.DATA选项
用于指明所需处理的数据集名,请注意在这里它是一个选项参数而不是语句。
2
2.VAR语句
如果只想分析某一个或几个特定的变量,则可用VAR语句指定它们。
例如在数据集中有x,y,z三个变量,如果只想显示变量x的列表,则PRINT过程如下:
Procprint;
Varx;
Run;
如果想显示x和y两个变量,则将VAR语句改为如下形式即可:
varxy;
3.WHERE语句
如果想分析的不是整个数据集而只是其中的某个子集,那么WHERE语句将会非常有用,如上例中我们只想显示大于50的x变量的值,则在PRINT过程中加入where语句如下:
wherex>50;
如果条件变为x、y两个变量的值都要大于50,则where语句改为:
wherex>50andy>50;
在SAS语言中常用的逻辑表达符号有and(和)、or(或)、xor(异或)、ne(不等)等。
它们均可在where语句中使用。
4.BY语句
By语句并非必须语句,它用于指定分组变量,如果需要分组处理数据,例如按性别分组输出统计结果,在过程步中有两种方式可以实现:
一是用不同的where语句将同一个过程步反复写几遍;
另一种显然更高效的方法就是采用by语句。
以便按照该变量的取值水平(或多个变量的水平组合)将数据集分组执行相应的分析过程。
如上例想按不同的y值输出x值,则可以加入by语句如下:
Byy;
在使用by语句时,SAS要求数据集已经使用sort过程按照相应的分组变量进行了排序。
若数据集末按照相应分组变量的字母顺序或数字顺序进行升序或降序排列,则程序执行将会出错。
SORT过程的语法说明详见下一章。
以上介绍的是最常用的几个语句,除此以外,freq语句、weight语句也非常常见,这里因篇幅所限,不再一一详述,读者请参见第6章中对这些语句用法的详细说明。
示例程序中的print过程在运行完毕后,LOG窗口中的输出如下:
7procprint;
8varx;
9run;
Therewere6observationsreadfromthedatasetA.LX1.
PROCEDUREPRINTused:
cputime0.01seconds
以上输出表明print过程调用的是数据集A.Lxl,相应output窗口中的输出如下:
obsx
11
22
33
44
55
66
其中obs列为记录号,x列则为输出的变量值
2.4程序的修改与调试
上面介绍了SAS程序的基本语法格式,由于SAS程序非常的复杂,实际使用中需要不断地进行修改和调试,这里以一个存在错误的程序为例,来学习如何在SAS8.2中进行程序的调试。
首先,请在PGM视窗中键入以下程序(见图2.1)。
图2.1调试SAS程序实例
选择下拉菜单Locals→Run,或直接按下F8键,程序及被提交运行。
大家可以看到视窗中不断出现各种信息,最后出现了红色的“Error”提示,表明该程序有错(见图2.2)
图2.2程序运行后的LOG视窗输出
LOG窗口的输出显示程序中共发现了二处错误,并分别给出了错误代码。
由于前面的错误可能会打乱后面语句的正确读入,因此程序的修改应当从第一处错误起顺序进行。
第一个错误在第7行,相应的错误代码为14。
下面有具体的代码解释;
WARNING14-169:
AssumingthesymbolPROCwasmisspelledasprc.
这一句表明,系统警告我们可能将“proc”拼成了“prc”。
显然,这是一个拼写错误。
改正的办法是将prc更正为正确的proc,然后重新提交运行,此次运行仍然没有得到正确的结果,LOG窗口相应输出的错误部分如下:
16procprint
SCLsourceline.
17run;
---
22
-
200
ERROR22-322:
Syntaxerror,expectingoneofthefollowing:
;
DATA,DOUBLE,HEADING,
LABEL,N,NOOBS,OBS,ROUND,ROWS,SPLIT,STYLE,UNIFORM,WIDTH.
ERROR200-322:
Thesymbolisnotrecognizedandwillbeignored.
18quit;
结果显示“run;
”语句所在行有误,错误代码为22和200。
但是很显然,这是一句标准的SAS语句,没有任何错误,是什么原因导致本行报错?
经检查发现,原来错误是出在上一行,是“print”后面少了一个分号,而SAS语句是以分号为语句结束符的,从而使系统认为这两句是一个程序行,并将“run”判为“print”的参数,自然无法识别。
改正时在print后加上分号即可,然后重新运行。
这一次LOG窗口没有报告错误,output窗口总则给出了相应的运行结果。
在SAS程序的调试中,由于前面的语句错误导致后面的语句报错是非常常见的现象,因此当程序中出现错误,而相应的错误出现在行的语句明显无误时,则应当重点考察紧邻它的上一条语句是否有误。
大多数情况下均可以找到错误出处。
但是,在个别复杂的SAS程序中,错误也有可能是相隔很远的语句错误所致,此时就需要从程序步开始进行检查。
2.5结构化语句简介
每一种结构化语言编写的程序都由顺序、分支、循环三种结构构成,SAS语言也不例外,在这里简要介绍一下分支和循环语句的语法。
这些语句均可直接在数据步中使用,熟练它们的用法可以大大简化我们的工作。
2.5.1分支(条件)语句
在SAS中的条件语句由IF…Then组合与Select…When两种,其中以前者最为常用。
1.IF…THEN语句
其语法格式如下:
IF条件THEN
程序块
ELSE
else语句及其后的语句块可以省略。
可见其语法和大多数编程语言十分相似。
需要注意的是,如果程序块只有一句,则可直接写出(不要忘记了结束时的分号),否则应以DO开头,以END结束。
例2.1在产生数据集case2_2的同时为其增加变量class,当x>
50时class=1,否则class=2.
解:
程序如下:
datacase2_2;
定义要建立的数据集为work.case2—2
inputxy@@;
要输入的变量为X和Y,采用连续读入方式
ifx>
50thenclass=l;
建立新变量CLASS,如果X>
50,则CLASS=1
eIseclass=2;
否则,CLASS=2
cards;
数据块开始
345678903567891023657745数据块
数据块结束
run;
数据步结束,开始运行以上程序
上面的程序运行完毕后,生成的work.case2_2内容如图2.3所示。
图2.3使用IF语句后生成的数据集
但是,以上程序为什么可以这样写?
在这里有必要解释一下数据步的执行过程,input语句按变量顺序将数据读入内存缓冲区,直至每一个变量都有值相对应。
然后数据步继续向下执行,从而其他语句可以修改内存缓冲区,如修改值、增加变量等,在执行到数据步结束后,程序又回到input语句处继续执行,直到数据读完为止。
现在再看看这个程序,大家可以理解它了吧!
2.SELECT….WHEN语句
SAS除了IfThen语句之外还提供了SeIectWhen语句进行分支选择,这个语句的基本使用方式有两种,分别为:
SECLET(表达式);
SELECT;
WHEN(数值1)执行语句A;
WHEN(条件1)执行语句A;
WHEN(数值2)执行语句B;
WEHN(条件2)执行语句B;
……
OTHERWISE执行语句Z;
OTHERWISE执行语句Z;
END;
例如本例如果使用select语句,则程序如下:
datacase2_2;
inputxy@@;
select;
when(x<
50)class=l;
when(x>
=50)class=2;
otherwise;
end;
345678903567891023657745
run;
2.5.2循环语句
1.Do…END语句
循环语句在SAS中有好几种方式实现,但以do…end最为常用,其语法格式如下:
DO起始条件TO终止条件;
END;
该语句主要用于建立数据集。
例2.2在产生数据集case2_2的同时为其增加变量class,取值依次为1、2。
定义要建立的数据集为work库的case2_2
doclass=lto2;
循环开始,控制变量为class,取值从l到2
要输入的变量为x和y,采用连续读入方式
output;
用output语句将变量值写成数据集中的纪录
循环结束
345678903567891023657745数据块
注意在数据步中不需要用语句改变循环变量的大小,系统会自动改变。
上面的程序运行完毕后,生成的wok.case2_2内容如图2.4所示。
图2.4使用循环语句后生成的数据集
程序中用到的output语句强行要求将当前数据存为一条新的记录,否则程序将会在运行到“run;
”语句时才生成新的纪录。
本例中如果不使用output语句,则系统会在循环过程中重复执行两次input语句,但只在数据步执行完后才生成纪录,最终数据文件中只有三条记录,且class取值均为循环结束时的3,如图2.5所示。
读者可以比较两种输出结果,以更清楚地理解循环语句和output语句的执行方式。
图2.5不使用循环语句时生成的数据集
2.其他循环语句
另外两种循环的实现语句为DOWHILE和DOUNTIL,它们的语法和使用方式较为简单,这里给出语法格式如下:
DOWHILE循环满足的条件;
DOUNTIL循环终止条件;
循环体语句;
循