1、第第3章章 SAS函数与函数与CALL子程序子程序清华大学经管学院清华大学经管学院 朱世武朱世武SAS函数定义函数定义 SAS函数是一个子程序,对自变量返回一个结果值。SAS函数的形式:函数名函数名(X1, X2, )函数用于组合表达式可以简化编程和统计计算函数用于组合表达式可以简化编程和统计计算例3.1 表达式中用函数。data a(keep=date y d min); /*保留date, y, d, min四个变量*/set ResDat.idx000001;y=year(date); /*函数year给出变量date年份*/d=weekday(date); /*函数weekday给出变
2、量date在一周内的哪一天*/min=min(sum(oppr, hipr, lopr,clpr),1000); run;例3.2 条件语句中使用函数。data a;set ResDat.idx000001;where year(date)1996; /* Where语句中使用Year函数 *run;用函数处理多变量可以简化程序用函数处理多变量可以简化程序例3.3 用与不用SAS函数时的程序。不用SAS函数。totx=xl+x2+x3+x4+x5+x6+x7+x8+x9+x10; if totxy then least=totx;else least=y;使用SAS函数。leastmin(su
3、m(of x1-x10),y);例中,两段程序的结果相同,第二段只有一个语句,非常简单。函数自变量函数自变量自变量类型: 变量名; 常数; 函数; 表达式。例3.4 函数及其自变量类型举例。 函数举例自变量类型Max(X,Y);变量名X,YX=Repeat(-, 20);常数LeastMin(sum(of x1-x10),y);变量名和函数自变量个数: 有些函数不需要自变量,有些只需要一个自变量,有些函数有多个自变量。SAS9.1中,自变量个数不能超过32767。 如果函数的自变量是表达式,在函数被调用之前,所有表达式自变量首先计算。自变量表示法:当函数有多个自变量时,必须用逗号分隔开。自变量
4、名缩写方法: 函数名(OF变量名1变量名n ) 例3.5 正确与错误的表示方法。例3.6 数组元素自变量的缩写方法。array y10 y1-y10; /*定义数组y10 */x=sum (of y*);z=sum (of y1-y10);例中,两个SUM函数的表示法是等价的。 正确的表示方法错误的表示方法sum (x, y, z)sum (x y z)sum (of x1-x10)sum (x1-x10)sum (of x1-x10 d y1-y100)sum (x1-x10 d y1-y100)函数结果函数结果通常函数的结果由其自变量的属性决定: 自变量是字符时结果变量为字符; 自变量是数
5、值时结果变量为数值。PUT函数是一个例外,它不管自变量是什么类型,其结果总是字符值。根据缺省规则,对大多数函数来说,数值目标变量的长度是8,字符目标变量的长度没有缺省规则 。目标变量长度不用缺省规则的函数见课本表3.1。用用PUT语句在语句在LOG窗口显示窗口显示函数值函数值例3.7 显示概率值和分位数。data;Y=probnorm(1.96); /* 标准正态分布小于1.96的概率 */put Y;q1=tinv(.95, 2); /*自由度为2的t分布的0.95分位数*/q2=tinv(.95, 2, 3); /*自由为2,非中心参数为3的t分布的0.95分位数*/put q1= q2=
6、;run;0.9750021049q1=2.9199855804 q2=13.894376071日期时间函数日期时间函数 SAS日期和时间存贮标准是以1960年1月1日0时0分0秒为起点,然后以相应的间隔记时。如1960年1月1日9时0分,按日记的数值就是0,按小时记的数值就是9。1960年1月2日0时0分,按日记的数值就是1,按小时记就是24等。 由于日期函数是一类非常重要的函数,特别是对金融数据处理和金融计算,借助日期函数可以极大提高效率。应用举例应用举例 例3.8 计算两个日期之间的天数。data _null_;sdate=01jan2002d;edate=01jan2003d;actu
7、al=datdif(sdate, edate, act/act); /*按每个月的实际天数算 */days360=datdif(sdate, edate, 30/360); /*按每个月30天计算 */put actual= days360=;run;data _null_;actual=datdif(01jan2002d, 01jan2003d, act/act);days360=datdif(01jan2002d, 01jan2003d, 30/360);put actual= days360=;run;例中,两段程序的结果一样。actual=365, days360=360.例3.10
8、以日为单位计算当前日期的天数。data;x=date (); y=today();put x= y=;run;例中,DATE()和TODAY()结果一样,都是返回当天的天数。当然,也可以用一定的日期格式表示它们。data;x=date (); y=today();format x y yymmdd10.;put x= y=;run;结果显示:x=17232 y=17232结果显示:x=2007-03-07 y=2007-03-07例3.12 计算日期值所在的年季月以及处于某月的第几天。data a;set ResDat.stk000001 (obs=10);keep date year qtr
9、 month day;year=year (date);qtr=qtr (date);month=month (date);day=day (date);proc print noobs;run; Date year qtr month day1991-01-02 1991 1 1 21991-01-03 1991 1 1 3 1991-01-04 1991 1 1 4 1991-01-05 1991 1 1 5 1991-01-07 1991 1 1 7 1991-01-08 1991 1 1 8 1991-01-09 1991 1 1 9 1991-01-10 1991 1 1 10 19
10、91-01-11 1991 1 1 11 1991-01-12 1991 1 1 12例3.14 将日期时间值换算为以秒计数的计算方法。data;mdy=mdy (08,18,2001); put mdy=;format mdy yymmdd10.;hms=hms (21,50,51); put hms=;x=21*60*60+50*60+51; put x=;dhms=dhms (date (), 21,50,51); put dhms=;dhms=dhms (15263,21,50,51); put dhms=;y=15263*24*3600+x; put y=;run;结果显示:mdy=
11、2001-08-18hms=78651x=78651dhms=1347832251dhms=1318801851y=1318801851 概率分布函数概率分布函数标准正态分布标准正态分布 PROBNORM(X)计算标准正态分布随机变量小于X的概率。 例3.15 计算三个特殊的正态概率值。data;P1=probnorm(0);P2=probnorm(1.96);P3=probnorm(2.5758293);put P1= P2= P3=;run;结果显示:P1=0.5P2=0.9750021049P3=0.9949999999样本统计函数样本统计函数 样本统计函数在实际中的用处不是很大,因为应
12、用这些函数时,一定要把样本的观测数据放在同一行才可以,现实中样本的观测数据却往往是按一列一列排的。一般情况下,求变量X的样本统计函数值时要用别的方法。样本统计量函数共有15个。 均值均值 MEAN(of xl-xn) 或 MEAN(x,y,z, )计算非缺失自变量的算术平均。自变量中至少有一个非缺失值。 求和求和 SUM(of xl-xn) 或 SUM (x1,x2, )计算自变量的和。要求有两个以上自变量。 方差方差 VAR(of xl-xn) 或 VAR (x1,x2, )计算自变量中非缺失值的方差。要求至少有两个自变量。 随机数函数随机数函数 SAS系统提供11种随机数函数。由于随机数函
13、数是进行随机模拟的基础,这里我们通过例子,给出每种随机数发生程序,供读者参考。 正态分布正态分布 例3.27 用函数RANNOR产生正态分布随机数。data RV;retain _seed_ 0; /*retain 赋初值0给_seed_*/mu=0;sigma=1; do _i_ = 1 to 1000;Normal1 = mu + sigma * rannor(_seed_); /*均值为mu,标准差为sigma*/output;end;drop _seed_ _i_ mu sigma;run;Normal1-0.9721-0.70001-2.34007-0.10939-0.01883-0
14、.641540.8187660.221107例3.28 用函数NORMAL产生正态分布随机数。data RV;retain _seed_ 0;mu=0;sigma=1;do _i_ = 1 to 1000;normal1 = 0 + 1 * normal(_seed_);/*均值为mu,标准差为sigma*/output;end;drop _seed_ _i_;run;均匀分布均匀分布 例3.29 用函数RANUNI产生均匀分布随机数。data RV1; retain _seed_ 0; a=-1; b=2; do _i_ = 1 to 1000;uniform1 = a + (b-a) *
15、ranuni(_seed_); /*区间a, b上的均匀分布*/output;end;drop _seed_ _i_;run;例3.30 用函数UNIFORM产生均匀分布随机数。data RV1; retain _seed_ 0; a=-1; b=2; do _i_ = 1 to 1000;uniform1 = a + (b - a) * uniform(_seed_); /*区间a, b上的均匀分布*/output; end; drop _seed_ _i_;run; 随机数函数自变量随机数函数自变量SEED 随机数函数使用一个自变量SEED来选择产生随机数的初始种子值,由这个值开始产生随机
16、数流。自变量SEED的取值和初始化类型如下表列出。 表3.4 SEED取值与初始化类型 自变量SEED初始化类型0等价于用计算机的日期时间值作为初始种子值来初始化随机数流0用自变量SEED的值作为当前的初始种子值来初始化随机数流产生随机数的过程中,自变量SEED的值保持不变,种子则不断变化。所以,用随机函数产生随机数时,不能控制种子的值,因此也不可能控制初始化之后的随机数。如果要控制随机数流,就要用随机数函数的CALL子程序。 SAS CALL 子程序子程序 SAS系统提供一系列CALL子程序,用于产生随机数或执行其它的系统功能,详见表3.5,3.6。 随机数子程序随机数子程序 用随机数子程序
17、可以更好地控制种子流和随机数流。除NORMAL和UNIFORM这两个函数之外,所有随机数函数都有一个相应的子程序。CALL语句激活随机数子程序的格式为:CALL routine (seed, variate);选项说明: 使用CALL子程序时,首先要对SEED变量赋初值。同时产生几个随机数流时,用CALL子程序比用随机函数的效果更好。因为,用随机数函数同时创建的多个随机数变量都属于同一个随机数流。 RoutineSAS随机子程序名Seed存放当前种子值的变量Argument特殊分布要求的参数Variate存放生成随机数的变量名例3.38 使用随机函数产生两个随机数变量属于同一个随机数流。dat
18、a RV;retain seed1 seed2 161321804;do I=1 to 5;x1= ranuni(seed1);x2= ranuni(seed2);output;end;options nocenter;proc print;run;例中,SEED1和SEED2的初值相同,但X1和X2的第一个观测值却不相同。因为,SEED2的值在这里不起作用,X2的第一个值并不是由SEED2产生的,而是产生第一个X1后一个新种子的结果。所以,这里产生的两个随机数变量属于同一个随机数流。 结果显示:结果显示:Obs seed1 seed2 I x1 x2 1 161321804 16132180
19、4 1 0.43617 0.64888 2 161321804 161321804 2 0.34138 0.42729 3 161321804 161321804 3 0.43237 0.63834 4 161321804 161321804 4 0.74690 0.89710 5 161321804 161321804 5 0.13630 0.19031例3.39 使用CALL子程序产生两个独立的种子流和随机数流。data RV;retain seed3 seed4 135279821;do I=1 to 5;call ranuni(seed3, X3);call ranuni(seed4,
20、 X4);output;end;proc print;run;例中,产生两个独立的种子流和随机数流。因为SEED3=SEED1,所以X3表示的随机数流就是X1和X2组成的随机数流。使用CALL语句时随时可以看到当前的种子值,用随机数函数则看不到。 结果显示:结果显示:Obs seed3 seed4 I X3 X41 936674311 724196333 1 0.43617 0.337232 1393460745 1733883844 2 0.64888 0.807403 733112270 1200908019 3 0.34138 0.559224 917607517 674688435 4
21、 0.42729 0.314185 928513130 1646762308 5 0.43237 0.76683第第4 4章章 访问外部数据文件访问外部数据文件清华大学经管学院清华大学经管学院 朱世武朱世武ZResdat样本数据:样本数据:SAS论坛:论坛: 本章内容本章内容v通过IMPORT过程导入外部数据文件;v通过LIBNAME语句和库引擎连接外部数据文件;v通过SAS/ACCESS软件访问外部数据文件;v通过ODBC或远程软件平台访问外部数据文件;v创建SAS数据集方法总结。 注意:本章的一些例子需要较为复杂的软硬件环境,可能无法在单个PC机上实现操作。 访问两类外部文件访问两类外部文
22、件 SAS系统访问的外部文件可以分为两类: PC格式的数据文件; 流行数据库(DBMS)文件。 PC格式的数据文件流行数据库文件DBFOracleDIFDB2WK1,WK3,WK4SybaseEXCEL4, EXCEL5,EXCEL97, EXCEL2000MS Access访问外部数据文件方法访问外部数据文件方法 除了前面两章介绍的读入外部数据文件的方法外,SAS系统访问外部文件,特别是流行数据库文件的方法还有以下几种。 通过IMPORT过程; 通过LIBNAME语句和库引擎; 通过ACCESS过程; 通过ODBC或远程软件平台。通过通过IMPORT过程过程 IMPORT过程可以导入的外部数
23、据文件:n PC格式的数据文件;n 以固定字符为字段分隔符的文本文件。 句法与选项说明句法与选项说明 PROC IMPORT DATAFILE=filename“ | TABLE=tablename OUT=SAS-data-set ; 选项说明: DATAFILE=规定要读入外部文件的地址及名称TABLE=规定外部数据文件中的表名OUT=规定要输出的SAS数据集DBMS=规定外部数据文件格式的标识名REPLACE规定替换已存在文件应用举例应用举例 例4.1 导入EXELL数据表。proc import out=tb31datafile= D:ResDattable.xlsdbms=excel
24、2000 replace;range=3#1$; /*导入表3.1 */getnames=yes;run;例4.2 从文本文件的第二行导入数据。proc import out=b_share_1datafile= D:ResDatb_shares_1.txtdbms=dlm replace;getnames=no;datarow=2;run;通过通过LIBNAME语句和库引擎语句和库引擎 通过LIBNAME语句和库引擎连接的外部文件有两类: 其它SAS版本或分析软件的数据集; 流行数据库(DBMS)。语句格式: LIBNAME libref SAS/ACCESS-engine-name ; B
25、MDPCRSPACCDB2FAMECHLIODBCOLEDBORACELOSIRISREMOTEREMOTE6REUTERSSPSSSYBASETERADATAV6V604V8XMLXPORTSAS8.2系统支持的库引擎 读入其它版本或分析软件数据集读入其它版本或分析软件数据集 可以通过菜单建立新逻辑库和利用LIBNAME语句连接其它SAS版本或分析软件的数据集。例4.5 连接SAS6版本数据集。libname datav6 V6 d:ResDat;run;例4.6 连接SPSS数据集。libname spss spss d: ResDat ;run;读入流行数据库(读入流行数据库(DBMS)
26、 读入流行数据库时需要知道这些数据库的简单操作。同样可以通过菜单建立新逻辑库和利用LIBNAME来实现。例4.7 用LIBNAME建立与ORACLE DBMS的连接。libname oralib oracle user=ZSW password=ZSW321path=ora7db dbindex=y;例4.8 取消逻辑库指定。libname oradb clear;例4.9 与DB2的连接。libname db2lib db2 authid=ZSW ssid=ZSW321;通过通过ACCESS过程过程 通过ACCESS过程可以实现对外部数据文件的透明访问和读写。SAS/ACCESS可以访问的主
27、要外部数据文件: IMS-DL-ISQL/DSDB2ADABASRdbOracleSybaseIngresInformixDBF/DIFExcelODBCACCESS过程访问外部数据须分两步完成: 创建访问描述器(Access Descriptor); 创建基于外部数据文件的数据视窗(View)。ACCESS过程访问外部数据流程图过程访问外部数据流程图 其它平台数据库文件访问描述器Access数据视图SAS程序Access数据视图Access数据视图 SAS系统通过不同的方法建立不同的数据视窗,除了这里用ACCESS过程建立ACCESS视窗外,还有用数据步和SQL过程建立的视窗。它们都能透明访
28、问不同平台上的数据对象。 创建访问描述器创建访问描述器 语句格式:PROC ACCESS DBMS=DBF|DIF|WKn|XLS|; CREATE libref.member-name.ACCESS; required database-description statements; optional editing statements; RUN;创建访问描述器的SAS程序对于不同的外部文件有不同的形式。下面给出几种外部文件访问描述器的创建方法。 由由DBF文件创建访问描述器的一般格式:文件创建访问描述器的一般格式:PROC ACCESS DBMS=DBF; CREATE 逻辑库名.访问描
29、述器名.ACCESS; PATH=DBF文件的地址和全名;Run;由由EXELL表创建访问描述器的一般格式:表创建访问描述器的一般格式:PROC ACCESS DBMS=XLS; CREATE 逻辑库名.访问描述器名.ACCESS; PATH=XLS文件的地址和全名; /*规定运行时在LOG窗口显示列的信息 */RUN;由由ORACLE数据库创建访问描述器的一般格式:数据库创建访问描述器的一般格式:PROC ACCESS DBMS=Oracle; CREATE 逻辑库名.访问描述器名.ACCESS; USER=Oracle用户ID;ORAPW=Oracle服务器上的用户密码;TABLE=Ora
30、cle表名;PATH=Oracle驱动器、结点和表的别名或库名;RUN;例4.10 由XLS表创建访问描述器RESDAT.S000001.ACCESS。 proc access dbms=xls; create work.s000001.access; path=D:ResDatstk000001.xls; getnames yes; scantype=yes; list all; run;例4.11 由DBF文件创建访问描述器RESDAT.A600002.ACCESS。 proc access dbms=dbf; create resdat.stk000002.access; path=D:
31、resdatstk000002.dbf; list all; run; 创建数据视窗创建数据视窗 通常基于一个访问描述器可以创建多个数据视窗。SAS数据视窗(View)和SAS数据集(Data)都是数据文件,均可以作为数据对象被引用。虽然类型不同,但在同一逻辑库中名称不能重复。 创建基于访问描述器数据视窗的语句格式创建基于访问描述器数据视窗的语句格式PROC ACCESS DBMS=DBF|DIF|WKn|XLS| ACCDESC=libref.access-descriptor; CREATE libref.member-name.VIEW; SELECT column-list; opti
32、onal editing statements; RUN;创建基于访问描述器的数据视窗的一般格式PROC ACCESS DBMS=数据库类型ACCDESC=访问描述器名; CREATE 逻辑库.视窗名.VIEW; SELECT ALL|DBMS表的列名; RUN;当然,对于不同的DBMS还有许多不同的控制语句。 同时创建访问描述器和数据视窗的语句格式同时创建访问描述器和数据视窗的语句格式PROC ACCESS DBMS=DBF|DIF|WKn|XLS|;CREATE libref.member-name.ACCESS; required database-description stateme
33、nts; optional editing statements; CREATE libref.member-name.VIEW; SELECT column-list; optional editing statements; RUN;例4.12 创建DBF文件的数据视窗。proc access dbms=dbf accdesc=work.s000002;create work.s000002.view;select all;list view;run;例中,基于访问描述器RESDAT.s000002.ACCESS创建D B F 文 件 s t k 0 0 0 0 0 2 . D B F 的
34、 数 据 视 窗WORK.s000002.VIEW.由数据视窗创建数据集由数据视窗创建数据集 实现这一目标的方法很多,如数据步、ACCESS过程等。例4.15 利用数据步将视窗转换为数据集。data stk000001;set s000001;run;ACCESS过程将数据视窗转换为数据集格式:PROC ACCESS VIEWDESC=数据视窗名数据视窗名 OUT=数据集名数据集名;例例4.16 ACCESS过程将数据视窗转换为数据集。PROC ACCESS VIEWDESC=s000001 OUT=stk000001;Run;通过通过ODBC ODBC(Open Database Conne
35、ctivity)技术是由微软提供的一个应用程序(API)接口标准。用于支持ODBC软件之间的数据访问。支持ODBC的外部数据文件系统: MS AccessTextTeradataMS ExcelOracleINGRESDBaseSybaseSQL ServerParadoxDB2AS/400BtrieveINFORMIXRedbrick创建创建ODBC数据源数据源 v通过ODBC访问外部数据文件的前提是创建ODBC数据源。v不同的外部数据文件系统创建ODBC数据源的方式也不一样。创建创建ODBC引擎逻辑库引擎逻辑库 v这里只给出用菜单方式由ODBC数据源创建SAS逻辑库,实现对外部数据文件的访问。用SQL编程实现对外数据ODBC数据源的访问方法可以参考相应的技术资料,这里从略。v利用前面创建的ODBC数据源TABLE和DISTS, 用菜单创建新逻辑库的方式创建SAS逻辑库ODBC1和ODBC2,读者自行操作。v实际应用时,通过ODBC访问后台数据库SQL-Server是非常简单和有效的方法。