SAS编程基础:金融建模与计算
1. SAS数据类型
数值型: 12, -7.5, 2.5E-10
字符型: ”Li Ming”, ‘YiWu’, ‘吴奕’ 注:定义字符型格式,如:”$8.”, 小数点不可丢
日期型:’08Sep2010’d
时间型:’14:20’t
日期时间型:’08Sep2010:14:20:32’dt
2. SAS运算符
算术运算符: + - * / **
比较运算符: <, =, >, <=, >=, ^=, IN
LT, EQ, GT, LE, GE, NE, IN
逻辑运算符: & (AND) | (OR) ˆ (NOT)
其他运算符:||(连接两个字符串),<>(取两个中大的一个),><(取两个中小的一个)
3. 用Input语句进行数据录入
1) Input语句的自由格式
条件:
a) 数据每行为一个观测,各数据值之间用空格或制表符分隔;
b) 无论是字符型还是数值型数据,缺失时都用小数点表示;
c) 字符型数据长度不能超过8个字符,中间不允许有空白,首尾如有空白则被忽略;
d) 在Input语句中必须列出观测中每一项数据对应的变量名,而不能省略中间的某一个。
例如:
Data LearnSAS.Exam1;
input var1 var2;
var3=dif1(var2);
time=intnx('month','01jul2005'd,_n_-1);
format time date.;
put time var1; /*在LOG窗口显示time和var1的值*/
put time= var1=; /*在LOG窗口显示time和var1*/
cards;
112.85 15.21
1223.29 14.23
124.41 14.69
15.21 13.27
154.23 16.75
13.56 185.33
;
run;
2) Input语句的列方式
条件:
a) 要求数据行各项上下对齐;
b) 各行之间没有任何分隔,连续写在一起;
c) 字符型数据长度可以超过8个字符,中间允许有空白,首尾如有空白则被忽略;
d) 无论字符型还是数据型变量,如果指定列位置都是空白,则输入值为缺省值,用小数点表示;
e) 可以只输入数据行中的某些项而忽略其他项。
例如:
Data LearnSAS.Exam2;
input name $ 1-11 sex $12-17 year 24-27 month 28-29 day 30-31;
date=MDY(month,day,year);
Attrib date Label="日期" format=yymmdd10.
name Label="姓名"
sex Label="性别";
cards;
Wu Yi Male 340203200305046515
Yang JunhaoFemale210201200207021618
Cheng Tong Female210404200206031516
Cheng ZitaoMale 210703200303021315
;
run;
4. 读入外部文件
1) 读入文本格式的数据文件,如“读入D盘USERS文件夹里SAS文件夹下的stud.txt文件”
Data LearnSAS.Exam3;
InFile ‘D:\Teaching\课程讲义\金融建模与计算2010\SAS基础程序\stud.txt’;
/*InFile语句应该放在Input语句前面*/
Input name $ 1-10 sex $ math chinese;
Run;
2) 读入其他微机文件,如“读入D盘USERS文件夹里SAS文件夹下的stud.xls文件”
Proc Import out=LearnSAS.Exam4
DataFile='D:\Teaching\课程讲义\金融建模与计算2010\SAS基础程序\stud.xls'
/*InFile语句应该放在Input语句前面*/
DBMS=Excel2000 Replace;
GetNames=Yes;
Run;
3) 与大型数据库接口,如在数据库服务器Server_SFS中有一个数据库Finance,其中有一个表Sales,用户名Guest,密码anyone
Proc Access DBMS=SyBase;
Create ResDat.sales.Access;
/*生成访问描述文件*/
Server=‘Server_SFS’;
DataBase=‘Finance’;
Table=‘Sales’;
User= Guest’;
Password=‘anyone’;
Create ResDat.sales.View;
/*生成访问描述文件*/
Select All;
Run;
注:美国Sybase公司研制的一种关系型数据库系统,是一种典型的UNIX或WindowsNT平台上客户机/服务器环境下的大型数据库系统。Sybase提供了一套应用程序编程接口和库,可以与非Sybase数据源及服务器集成,允许在多个数据库之间复制数据,适于创建多层应用。系统具有完备的触发器、存储过程、规则以及完整性定义,支持优化查询,具有较好的数据安全性。Sybase通常与SybaseSQLAnywhere用于客户机/服务器环境,前者作为服务器数据库,后者为客户机数据库,采用该公司研制的PowerBuilder为开发工具,在我国大中型系统中具有广泛的应用。
5. 数据集的复制与修改
用Set语句可以进行数据集的复制,配合使用If, Keep, Drop等语句可以进行数据集修改
1) 数据集复制,格式:
Data 目标逻辑库名.目标数据集名;
/*数据集必须为SAS数据集*/
Set 原始逻辑库名.原始数据集名;
/*数据集必须为SAS数据集*/
Run;
假如想把ResDat数据库下的数据集Exam复制到Work逻辑库下,命名为aaa,则
Data Work.aaa;
Set ResDat.Exam;
Run;
2) 数据集修改,格式:
Data 目标逻辑库名.目标数据集名;
/*数据集必须为SAS数据集*/
Set 原始逻辑库名.原始数据集名(数据集选项);
/*数据集必须为SAS数据集*/
Run;
其中
FirstObs=,表示从指定序号的观测值开始读取
Obs=,表示读取观测值时读到指定的序号(不是观测数)
Keep=,表示引入时只要指定的变量
Drop=,表示不引入指定的变量
注意:用Set语句修改数据集时,如果需要使用Last或First函数,则Set后必须有“By 变量”语句,否则Last或First函数无效。
如:
data Old;
array x(5);
do i=1 to 100;
do j=1 to 5;
x(j) = normal(0);
end;
output;
end;
drop i j;
run;
data New1;
set Old(FirstObs=2 obs=10 keep=X1 X2);
run;
data New2;
set Old(FirstObs=2 obs=10 Drop=X1 X2);
run;
3) 用Set和Output语句拆分数据集
目的:根据要求把数据行分别存放到不同的数据集中。
Data 目标逻辑库名.目标数据集名1目标数据集名2 ……; /*数据集必须为SAS数据集*/
Set 原始逻辑库名.原始数据集名(数据集选项);
/*数据集必须为SAS数据集*/
Select(判断变量名);
When(判断值1) output目标数据集名1;
When(判断值2) output目标数据集名2;
……
Otherwise put 判断变量名= ‘有错’;
End;
Run;
如:
Data Learnsas.Scores;
Input Name$ Sex $ math chinese English;
cards;
WuYi M 100 98 98
YangJH F 97 98 99
ChenT F 98 96 95
ChenZT M 98 99 100
;
Run;
Data Learnsas.Scores_M Learnsas.Scores_F;
Set Learnsas.Scores;
Select(Sex);
When('M') output Learnsas.Scores_M;
When('F') output Learnsas.Scores_F;
Otherwise put Sex='Error!';
End;
Drop sex;
Run;
4) 数据集纵向合并
目的:把几个相同结构的数据集上下连接到一起。
Data 目标逻辑库名.目标数据集名; /*数据集必须为SAS数据集*/
Set 原始逻辑库名.原始数据集名(数据集选项);
/*数据集必须为SAS数据集*/
Run;
如:
Proc sort data=Learnsas.Scores_M;
by name;
run;
Proc sort data=Learnsas.Scores_F;
by name;
run;
Data Learnsas.Scores_MF;
Set Learnsas.Scores_M Learnsas.Scores_F;
By name;
Drop sex;
Run;
5) 数据集横向合并
目的:把多个包含同样观测的不同属性的数据集横向合并在一起。
Data 目标逻辑库名.目标数据集名; /*数据集必须为SAS数据集*/
Merge 原始逻辑库名.原始数据集名1原始数据集名2……; /*数据集必须为SAS数据集*/
Run;
如:
Data Learnsas.Scores_new;
Input Name$ Sex $ physics chymist ;
cards;
WuYi M 100 100
YangJH F 95 85
ChenT F 85 98
ChenZT M 96 94
;
Run;
Proc sort data=Learnsas.Scores;
by name;
run;
Proc sort data=Learnsas.Scores_new;
by name;
run;
Data Learnsas.Scores_sum;
Merge Learnsas.Scores Learnsas.Scores_new;
By name;
Run;
6) 用UpDate语句更新数据集
目的:更改原始数据集中的错误数据或者更新原始数据集中的新数据
Data新数据集名; /*数据集必须为SAS数据集*/
Update原始数据集 更新用数据集名; /*数据集必须为SAS数据集*/
By 关键标量;
Run;
Data Old;
Input name$ sex$ math chin eng;
Cards;
YWu Male 100 98 97
JHYang Male 98 97 96
ZTChen Male 98 97 100
TChen Femal 97 100 99
;
Run;
proc sort data=Old;
by name;
run;
Data Use;
Input name$ sex$ math;
Cards;
JHYang Female .
ZTChen . 99
;
Run;
proc sort data=Use;
by name;
run;
Data New;
Update Old Use;
By name;
Run;
6. 日期格式
Yymmdd8. 结果示例:73-12-15
Yymmdd10. 结果示例:1974-12-15
7. Put语句
Put语句的输出结果在LOG窗口。例如:
data;
x=0.5;
y=sin(x);
put ‘Since function value of’ x ‘is’ y;
run;
显示结果:Since function value of 0.5 is 0.4794255386
data;
x=0.5;
y=sin(x);
put ‘Since function value of’ x= ‘is’ y=;
run;
显示结果:Since function value of x=0.5 is y=0.4794255386
data;
x=0.5;
y=sin(x);
put ‘Since function value of’ x 30-40 .6 ‘is’ y 50-60 .6;
run;
显示结果:Since function value of 0.500000is 0.479426
注:如果希望PUT输出结果不产生换行,只要在PUT语句结尾处加一个@符号即可,
如:put i @;
8. 分支结构
IF 条件 THEN 语句;
ELSE 语句;
注意:其中的语句均可为一个语句。
Data example;
x=2;
If x>1 then y=3;
Else y=0;
Put x= y=;
run;
注意:当需要使用复合语句时,只需要把若干个语句用“Do;”语句和“End;”语句包围起来,就可以把它们看作一个语句。
Data example;
x=2;
If x>0 then Do;
x=2*x;
Put x= '为正数';
End;
Else Put x;
Run;
9. 循环结构
1) 计数Do循环
Do 计数变量=起始值 To 结束值 By 步长;
循环体语句…….;
End;
如:
Data example;
Do i=1 to 50 by 2;
x=normal(0);
y=normal(0);
Output; /*如果没有这个语句,则只有一个观测值*/
End;
Drop i; /*i的值不输出*/
run;
注:在Do循环中,Leave语句表示跳出循环体,Continue表示结束本轮循环,进入下一轮循环。例如:
data;
do x=0 to 3.1415926 by 0.01;
y = sin(x);
if y<0 or y>0.5 then Continue;
z = cos(x);
put x 5.2 y 20.7 z 20.7;
output;
if x>=3 then Leave;
end;
run;
2) 当型Do循环
Do While循环继续条件;
循环体语句…….;
End;
如:
Data;
Do j=2 to 1000;
k=int(Sqrt(j));
i=2;
Do While(i<=k);
If mod(j,i)=0 then Leave;
i=i+1;
End;
if ik);
If mod(j,i)=0 then Leave;
i=i+1;
End;
if i [选项] ];
Plot <纵坐标变量*横坐标变量[=分层变量名]...> / [选项]; 指定绘图变量和选项
Plot2 <纵坐标变量*横坐标变量[=分层变量名]...> / [选项]; 在原图基础上重叠绘制第二幅散点图
Symboln [选项] 定义符号、添加趋势线、定义点和线的颜色
By <变量名列>; 按该变量取值分层绘制,要求数据集已按该变量排序
选项含义:
Overlay
把几个图形绘制在一张图上
VREF=a
在竖轴上的a处画一条垂直于此轴的参照线
V=
规定数据点的图形符号
H=
规定图形符号的高度
I=
规定两点之间的插值方法
Font=
规定字体
L=
规定点之间插值线的类型
C=
规定图形线的颜色
如:
proc gplot data= sasuser.example;
plot var1*time=1 var2*time=2 var3*time=3/overlay;
symbol1 c=red v=star i=join;
symbol2 c=black v=dot i=spline;
symbol3 c=green v=diamond i=none;
run;
15. 时间序列预处理
proc arima data= sasuser.example;
identify var=var2 nlag=3;
run;
proc arima data= sasuser.example;
identify var=var1 nlag=3 minic p=(0:5) q=(0:5);
run; 阴影给出限定阶数范围内BIC最小的模型阶数
16. 时间序列分析
proc arima data= sasuser.example;
identify var=var1;
estimate q=4;
run;
17. 表内数据选择
proc sql;
create table sasuser.example1 as
select * from sasuser.example where var1<10;
quit;
18. 表内数据增加列
proc sql;
alter table exam
add var5 int label='var5', var6 num label='var6';
两个var5可以不同名,前者为变量,后者为标签
select * from exam;
quit; 目前增加的列还没有信息,需要用update语句补充
proc sql;
update exam
set var5=1000,var6=var1/var2;
select * from exam;
quit;
19. 分类求和
data dset;
input x c;
cards;
-1 1
-2 1
2 1
. 1
1 3
2 3
3 3
;
Proc sql;
Create Table aa as
select c,sum(^missing(x))*avg(x)
from dset group by c;
Quit;
20. 求累积和
data a;
input a b;
datalines;
1 2
2 3
3 4
4 5
;
data aa;
retain c;
set a;
c=sum(c,a,b);
run;
简单方法: 使用“sum+求累积和变量名”,此处“sum”为求出的累积和变量名,如:
Data Temp;
Input x1 x2 x3;
sum+x3;
Cards;
1 2 3
2 3 4
3 4 5
5 6 7
;
Run;
21. 求累积乘积
%macro Prod(Name_Dat,variable); /*计算数据集Name_Dat中变量variable的连乘积*/
data &Name_Dat.(drop=b c log_&variable. sgn_&variable.);
retain b c &variable._prod;
set &Name_Dat.;
If &variable.=0 then &variable._prod=0;
Else Do;
log_&variable.=log(abs(&variable.));
If(&variable.<0) then sgn_&variable.=1;
Else sgn_&variable.=0;
b=sum(log_&variable.,b);
c=sum(sgn_&variable.,c);
If &variable._prod=0 then &variable._prod=0;
Else &variable._prod=(-1)**c*exp(b);
End;
proc print;
run;
Data &Name_Dat.;
Set &Name_Dat.;
%Mend Prod;
22. 求分类乘积
data dset;
input x c;
cards;
-1 1
-2 1
2 1
. 1
1 3
2 3
3 3
;
proc sql;
select c, (-1)**sum((x<0&^missing(x)))*(sum((x=0))=0)*exp(sum(^missing(x))*avg(log(abs(x)))) as productX from dset group by c;
quit;
23. 提取观测数和变量数
以Dat.class为例
%let dsid=%sysfunc(open(Dat.class,i));
%let n=%sysfunc(attrn(&dsid,nobs));
/*&n.=观测数*/
%let rc=%sysfunc(close(&dsid));
%let dsid=%sysfunc(open(Dat.class,i));
%let n=%sysfunc(attrn(&dsid,nvars)); /*&n.=变量数*/
%let rc=%sysfunc(close(&dsid));
24. 提取同一个文件夹下的文件名
%sysexec dir *.xls /b/o:n > flist.txt;
然后用Exit命令退出DOS
注意:该语句执行时要求文件夹为当前文件夹,即需要把SAS的当前文件夹修改成需要提取文件名的文件夹,否则出错。
25. 更改当前文件夹
找到SAS快捷方式(开始->程序->The SAS System->The Sas System for windows),右击->属性,在目标中的命令后加上
SASInitialFolder="文件夹绝对路径"
(原命令类似于:"C:\Program Files\SAS\SAS9.1.3.sas")
再点这个快捷方式
如:
sasInitialFolder="D:\Teaching\课程讲义\金融建模与计算2010\ResStk"
26. 正态性检验
Proc Univariate Data=数据集 Normal;
Var 变量;
Histogram 变量;
Probplot 变量;
Run;
SAS规则:当样本含量n ≤2000 时,结果以Shapiro - Wilk (W 检验) 为准;当样本含量n>2000 时,结果以Kolmogorov - Smirnov (D 检验) 为准。
1