SAS金融数据处理综合练习题
1.创建一包含10000个变量(X1-X10000),100个观测值的SAS数据集。分别用DATA
步,DATA步数组语句和IML过程实现。
(1)用data步实现
data test1a;
informat x1-x10000 9.2; /*创建100个变量,规定输出格*/
do i=1to100; /*做循环*/
output;/*每一次循环,输出所有的变量,包括i*/
drop i;/*去掉i*/
end;
run;
或者
data test1a;
format x1-x10000 best12.; /*创建10000个变量x1-x10000,但未有初始化*/
do i=1to100; /*创建100个观测*/
output;/*且每一个观测都输出到数据集test1a*/
end;
drop i;
run;
(2)用data步数组语句实现
data test1b;
array t{10000} x1-x10000 ;/*创建数组变量*/
do i =1to100;/*每个变量有100个观测*/
output;/*每一次循环,输出所有的变量,包括i*/
drop i;/*去掉i*/
end;/*循环结束*/
data test1c;
array t{10000} x1-x10000;
do j=1to100;/*100次观测的循环*/
do i = 1to10000;
t{i}=i;/*第i个变量等于i*/
end;
output;/*输出第i次观测的i个变量的值*/
end;
drop i j;/*去掉i和j*/
run;
或者
data test1b;
array t{10000} x1-x10000;
do j=1to100;/*100次观测的循环*/
do i = 1to10000;
t{i}=i;/*第i个变量等于i*/
end;
output;/*输出第i次观测的i个变量的值*/
end;
drop i j;/*去掉i和j*/
run;
(3)用IML过程实现
proc iml;/*启用iml环境*/
x='x1':'x10000';/*定义数组x1-x10000*/
t= j(100,10000,1) ;/*创建100行10000列的. 同元素矩阵*/
print t x;/*打印两个矩阵察看*/
create test1d from t[colname=x];/*创建数据集c,变量数为列数,观测数为行数,列名更改为变量名,默认逻辑库为临时*/
append from t; /*将t中的值填充的数据集中*/
show datasets;
show contents;/*显示数据集的一些7788的属性*/
close test1d;
run;
quit;
或者
proc iml;
x='x1':'x10000';
t= shape(1,100,10000) ;/*shape和j不太一样,顺序是元素,行,列,j的顺序为行,列,元素*/
print t x;
create test1d from t[colname=x];
append from t;
show datasets;
show contents;
close test1d;
run;
quit;
(4)用宏实现
%macro names(name,number,obs);
data a;
%do i=1%to &obs;
%do n=1%to &number;
&name&n=1;
%end;
output;
%end;
run;
%mend names;
%names(x, 10000,100);
2.多种方法创建包含变量X的10000个观测值的SAS数据集。
3.数据集A中日期变量DA TE包含有缺失值,创建包含日期变量DATE的数据集B,并填
充开始到结束日之间的所有日期值。
proc iml;/*启用iml环境*/
x= {'date' price};/*注意所用的括号类型*/
t= {11112,23412,21323,12345,123456,34566,67534,23457,21349};
print t;/*构造9行2列的向量*/
t[1,1]=.;
t[2,1]=.;
t[5,1]=.;
t[9,1]=.;/*令某些date的观测成为缺失值,包括第一个观测值*/
create a from t[colname=x];/*从矩阵构造数据集a,为变量命名date和price */ append from t; /*填充矩阵已有的观测值 */
show datasets;
show contents;/*显示一些信息,可省略*/
close a;
run;
quit;/*退出iml环境 */
data a;
set a;
format date yymmdd8.2;/*将数值型的改变为日期型的输出变量*/
run;
data a1;
set a ;
n=_n_;/*取出观测号,以方便进行排序 */
format date yymmdd8.2;
retain temp;/*设定一个变量temp,规定如果没有新的观测读入,不清空原值,保留原来的观测值 */
if date^=.then temp=date;/*如果读入的date的观测值不为空 */
else date=temp;
run;/*至此数据集填充了后面的部分,最之前的缺失值未能填充,后面将数据集逆序排列进行填充*/
data a2;
n=_n_;/*创建数据集c,取出c的观测号,以方便进行逆向排序*/
set a1;
run;
proc sort data=a2;
by descending n;/*将c逆向排序*/
run;
data a3;/*定义数据集d,填充数据集d的末尾的观测*/
set a2 ;
drop n temp;
run;
data a4 ;
set a3;
retain temp;
if date^=.then temp=date;
else date=temp;
run;
data a4;
n=_n_;
set a4;
run;
proc sort data=a4 out=b(drop=n temp);
by descending n;/*定义数据集e,将d中的观测最一次逆序,得到原序*/
run;
以下是助教的做法但是无法运行成功
proc sort data=a;
by date;
data b(drop=date);
set a end=end;
by date;
retain start;
if _n_=1then start=date;
if _n_=end then do;
last=date;
output;
end;
run;
data b(keep=date);
informat date yymmdd10.;
format date yymmdd10.;
set b;
do date=start to last;
output;
end;
run;
4.创建包含日期变量DA TE的SAS数据集,日期值从1900年1月1日到2000年1月1
日。
data test4a;
informat date 9.2 x y;
format date yymmdd10.2;/*规定输出格式*/
x=mdy('1','1','1900');/*返回sas日期值,即以1960/1/1为0的日期值*/
y=mdy('1','1','2000');
do i= x to y;
date=i;
output;
end;
drop i x y;
run;
或者
data test4b;
do date='1jan1900'd to'1jan2000'd;
output;
end;
format date yymmdd10.;
run;
5.利用随机数函数RANUNI对某数据集设计返回抽样方案。
data sample(drop =samplesize n);
samplesize=5; /*样本容量为5*/
do n=1to samplesize; /*从1到样本容量的循环*/
readit=ceil(ranuni(0)*totobs);
put readit=;
set resdat.class point=readit nobs=totobs;
output;
end;
stop;
run;
或者
data dat1;
set resdat.class;
keep name;
run;
%macro sample(i);
data dat2;
set dat1 nobs=nobs;
ran=ceil(nobs*ranuni(&i));
run;
proc sort data=dat2;
by ran;
run;
%mend sample(i);
%sample(2);
data dat3;
set dat2;
if _n_<=6;
run;
%sample(3);
data dat4;
set dat2;
if _n_<=6;
run;
%sample(5);
data dat5;
set dat2;
if _n_<=6;
%sample(30);
data dat6;
set dat2;
if _n_<=6;
run;
data a;
set dat3 dat4 dat5 dat6;
run;
或者
data a;
set resdat.class;
keep name;
run;
data b;
set a nobs=nobs;
ran=ceil(nobs*ranuni(2007));
run;
proc sort data=b;
by ran;
data c;
set b;
if _n_<=5;
run;
6.利用随机数函数RANUNI对某数据集设计不返回抽样方案。
data a;
set resdat.class;
keep name;
run;
data b;
set a nobs=nobs;
ran=ceil(nobs*ranuni(1));
put ran=;
run;
proc sort data=b;
by ran;
data c;
set b;
if _n_<=15;
run;
或者
data a;
set resdat.class;
keep name;
run;
data b;
set a nobs=nobs;
ran=ceil(nobs*ranuni(2007));
run;
proc sort data=b;
by ran;
data c;
set b;
if ran=lag(ran) then delete;
run;
data d;
set c;
if _n_<=15;
run;
7.计算数据集A中变量X的累乘。
proc iml;
x='x';
m=do(1,10,0.5);
t=t(m);
print m t;
create a from t[colname=x] ;
append from t;
quit; /*用IML生成数据集a*/
data b;
set a;
retain y 1;
y=y*x;
run;
或者
data a;
input x;
y=y*x;
retain y 1;
cards;
1
2
3
4
;
run;
8.如何改变一个SAS数据集的变量顺序?
data a(keep=name) b(keep=age) c(keep=weight) d(keep=height);
set resdat.class;
run;
data test8a;
merge b d c a;
run;
或者
data test8b;
format height weight age name;
set resdat.class;
run;
9.数据集A和B包含同样两变量DA TE和PRICE,以DATE为标识变量合并数据集A和
B为C。合并时应该注意什么?
在合并前必须先排序,并且merge a b; by date;与merge b a; by date;结果不一样。
proc sort data=a;
by date;
run;
proc sort data=b;
by date;
run;
data c;
merge a b;
by date;
run;
10.给下段程序的主要语句加注释。STOP语句能否删除?为什么?
data a; /*创建数据集a*/
do obsnum=1to last by20; /*做循环,从第一个观测到最后一个观测数,间隔20*/
set ResDat.stk000001 point=obsnum nobs=last; /*指针选项和观测总数选项*/ output;/*强制输出当前值,否则只会在最后输出现值*/
end;/*命令选换结束*/
stop;/*强制结束数据步,因为set语句在数据步程序中会反复执行数据步的程序直到遇到
文件结束(最后一跳观测)的标志,这里使用了指针选项可能碰不到这种标志,所以要用
stop,否则就有可能无休止地执行下去*/
run;
11.假设数据集A中的变量logdate为如下形式的字符格式:
1998-12-2
1999-8-6
1999-8-10
将其转换为日期格式变量date。
如果字符格式的数据为:
19981202
19990806
19990810
又怎样转换为日期格式变量。
data a;
input logdate $ 10.;
cards;
1998-12-2
1999-8-6
1999-8-10
;
run;
data b;
set a(rename=(logdate=date));
date=input(date,yymmdd10.);
label date= '日期';
run;
或者
data a;
input logdate $9.;
cards;
1998-12-2
1999-8-6
1999-8-10
;
run;
data b;
format date yymmdd10.; /*规定输出格式*/
set a;
date=input(logdate,yymmdd10.); /*转变格式*/
drop logdate;
run;
12.运行SAS程序过程中,SAS系统创建的自动变量是否包含在创建的数据集?一般情况
下,怎样查看系统自动变量的值?
自动变量是由数据步语句自动创建的,这些自动变量不输出到数据集中,在重复过程中被保留。
data a;
set resdat.class;
put _n_ _error_;
keep _numeric_;
run;
13.SAS系统显示表达式、函数、数据集、数组或矩阵的具体值时,常需要哪些语句和过程?
put; proc print ; print ;show ;list;
14.写出下面各段程序创建数据集的所有观测值,并指出PUT语句分别在LOG窗口输出什
么结果?
data a1; do n=1 to 5; output; end; put n=; run;
数据集a1中有一个变量n ,5个观测值为1-5,日志窗口输出n=6; data a1; do n=1 to 5; output;
put n=;
end; put n=; run;
数据集中有一个变量n ,5个观测为1-5,日志窗口输出n=1-n=6 data a1; do n=1 to 5;
put n=; end; put n=; run;
数据集中有一个变量n ,只有一个观测值6,日志窗口输出n=1-n=6 data a1; do n=1 to 5; end; put n=; run;
数据集中有一个变量n ,只有一个观测值6,日志窗口输出n=6 data a2; n=1;
do until(n>=5);
n+1; output; end; put n=; run;
数据集中有一个变量,4个观测,n=2-n=5,日志窗口输出n=5
data a3; n=1;
do while(n<5); n+1; output; end;
put n=;
run;
同上一题一样的情况,数据集中有一个变量,4个观测,n=2-n=5,日志窗口输出n=5 data a4; n=7;
do until(n>=5);
n+1; output; end; put n=; run;
数据集中有一个观测,n=8,日志窗口n=8。因为执行了一次数据步 data a5; n=7;
do while(n<5); n+1; output; end; put n=; run;
数据集中一个变量n ,没有观测,日志窗口n=7
15. 数据集A 有一个变量n ,5个观测值1,2,3,4,5。数据A1由下面程序2产生,同样有一个
变量n ,5个观测值1,2,3,4,5。试分析下面两段程序中,PUT 语句在Log 窗口输出结果的差异,为什么? 程序1: Data a; Set a; Put n=; Run;
在日志窗口中输出n=1-n=5 程序2: data a1; do n=1 to 5; output; end; put n=; run;
在日志窗口中输出
n=6
理解了set 语句就不难得到这个结果。
data a; do n=1 to 5; output ; end ; run ; Data a;
Set a;
Put n=;
Run;
data a1;
do n=1to5;
output;
end;
put n=;
run;
16.试由以下的9种德国马克对美元汇率看跌期权和9种英镑对美元汇率的看跌期权产生81
种组合。
一年期,DM/USD汇率的9种不同看跌期权的执行价格和成本
执行价格Kdm 成本Cdm
0.66 0.085855
0.65 0.032191
0.64 0.020795
0.63 0.017001
0.62 0.013711
0.61 0.010851
0.60 0.008388
0.59 0.006291
0.55 0.001401
一年期,BP/USD汇率的9种不同看跌期权的执行价格和成本
执行价格Kbp 成本Cbp
1.30 0.137213
1.25 0.082645
1.20 0.045060
1.15 0.028348
1.10 0.016146
1.05 0.007860
1.00 0.003277
0.95 0.001134
0.90 0.000245
创建样本数据集:
data dm;
input Kdm Cdm;
cards;
0.66 0.085855
0.65 0.032191
0.64 0.020795
0.63 0.017001
0.62 0.013711
0.61 0.010851 0.60 0.008388 0.59 0.006291 0.55 0.001401 ; run;
data bp;
input Kbp Cbp; cards;
1.30 0.137213 1.25 0.082645 1.20 0.045060 1.15 0.028348 1.10 0.016146 1.05 0.007860 1.00 0.003277 0.95 0.001134 0.90 0.000245 ; run; 解答:
data test16a;
set dm; /*依次读入数据集dm 中的第1至9个观测*/ do j=1 to 9 ; set bp point=j;/*在读入dm 的第i 个观测后,依次读入bp 中的所有观测*/
output ;
end ; run ;
或者
data test16b; do i=1 to 9;
set dm point=i; /*依次读入数据集dm 中的第1至9个观测*/ do j=1 to 9 ; set bp point=j;/*在读入dm 的第i 个观测后,依次读入bp 中的所有观测*/
output ;
end ; end ; stop ; run ;
17. 不用SAS 函数,用宏%a(n,p)计算二项分布的概率分布和累计概率(k=1,2……,n)。
()(1)k n k n P X k p p k -??
==- ???
。
(此处留有空白)
18.创建组标识变量GROUP,将数据集A中的观测等分为10组,观测值不能整除10时,
前余数组各多加一个观测值。
data a;
n=_n_;
retain groupid 0;
set test nobs=totobs;/*选项nobs观测的总数,赋值给totobs*/
x=mod(totobs,10);/*观测个数除以10的余数*/
y=int(totobs/10);/*观测个数除以10的整数*/
data a;
set a nobs=totobs;
if ( n>0 and n=<(y+1)*x) then
groupid= int((n-1)/(y+1))+1;/*前x组的号码*/
else
groupid= int((n-x-1)/y)+1;/*不多元素的组号*/
drop x y;
run;
19.现有一个数据流:a 2 b 3 c d 4 6,按下面要求创建SAS数据集。用语句input id $ no; 变
量id取值上面数据流里的a,b,c,d,变量no取值2,3,4,6。但是这个数据流存在问题:如有的id没有no,有的no没有id。创建SAS数据集,删除只有id没有no或者只有no 没有id的观测,即把上面的c和6去掉,最后得到三个观测,a 2, b 3与d 4。
data b;
input no $ @@;
id=lag(no);
cards;
a 2
b 3
c
d 4 6
;
run;
data d;
format id $8. no $8.;
set b;
if'a'<=no<='z' or '1'<=id<='9'then lostcard;
run;
或者
data a;
input t$@@; /*指针*/
cards;
a 2
b 3
c
d 4 6
;
data a;
set a;retain;
if'a'<=lowcase(t)<='z'then id=t;/* 如果是字符串,则用专门的函数判断 */ else do;
no=input(t,8.);
output;
no=.;
end;
drop t;
proc sort;
by id ;
data a;
set a;
if first.id;
run;
或者
data a;
input t$@@;
cards;
a 2
b 3
c
d 4 6
;
data b;
set a;
id=lag(t);
no=t;
if'a'<=id<='z' and '0'<=no<='9'then output;
drop t;
run;
20.现有一个数据流:a23 223 bc4 36 3c5 11d 400 620,按下面要求创建SAS数据集。
用语句input id $ no; 变量id取值上面数据流里的a23, bc4, 11d ,变量no取值233,36,400。但是这个数据流存在问题:如有的id没有no,有的no没有id。创建SAS数据集,删除只有id没有no或者只有no没有id的观测,即把上面的3c5和620去掉,最后得到三个观测:a23 223
bc4 36
11d 400
data a;
input t$@@;
cards;
a23 223 bc4 36 3c5 11d 400 620
;
data b;
set a;
isno=1;
do i=1to length(t);
if substr(t,i,1)<'0' or substr(t,i,1)>'9'then do;
isno=0;
return; /*结束循环,返回数据步开始 */
end;end;
data c;
set b;
char=lag(t);
lag_isno=lag(isno);
number=t;
if lag_isno=0 and isno=1then output;
keep char number;
run;
或者
/*基本思路是先将原数据读入,然后重新按输出为一列,使用lostcard语句读取数据,思路更简洁*/
/*读入数据,重新输出为一列*/
data_null_;
input t $ @@;
file'D:\a.txt';
put t $;
cards;
a23 223 bc4 36 3c5 11d 400 620
;
run;/*利用lostcard语句来选出正确的数据,其中no=. 说明将有非数字的字符的值读入数值变量,也就是连续的name的情况,舍去当前行,重新定位;如果idtest不为.说明读入的id是数值型的,就是连续id情况,舍去当前行,重新定位。这样就可以读出正确的数据了*/
data a (drop=idtest);
infile'D:\a.txt';
input id $ / no;
idtest=id+1;
if no='.' or idtest ne '.'then lostcard;
run;
或者
/*方法一,基本思路:先将数据流都读入到一个字数变量中,判断如果其有字符出现,则赋值给name,否则转化为数值后赋值给id当name和id值同时不为空时认为找到了一线数据,输出(对name,id都使用retain语句,输出后将前一步读入的数据清空).*/
data a;
informat temp $10.;
attrib name informat=$10.format=$https://www.doczj.com/doc/3116506230.html,bel="Name";
attrib id informat=best12.format=best12. lable="Id";
retain name "";
retain id .;/*先将数据流都读入到变量temp中*/
input temp :$10.@@;/*设计一个变量标记temp中的是否有字母,有值为1,否则为0,先设为零*/
flg=0;/*检验temp是否有字母*/
do i=65to90;
if index(upcase(temp),byte(i))^=0then do;/*如果发现一个字母,将flg 变量值改为1,退出循环*/
flg=1;
leave;
end;
end;/*根据以上的判断,如果temp中有字母,将其赋值给name,如果name不为空,转换为数值型赋值给id,否则舍去*/
if flg=1then do;
name=temp;
else if name^=""then id=input(temp,best12.);/*如果name和id同时不为空时说明找到了一组配对的数据,输出到数据集中,清空原有的值*/
if name^="" and id^=.then do;
output;
name="";
id=.;
end;
keep name id;
cards;
a23 223 bc4 36 3c5 11d 400 620
;
run;
或者
/*在上述的方法中,对于连续出现的name自动用后一个覆盖前一个林而保留正确的数据,对于连续出现的数字,通过判断是否有name与之配对而决定是否保留,从而选取出想要的数据.*/
/*上述方法可以进行两处修改和完善,
一:上面的程序只是判断了字符串中是否有字母,如果有字母才认为是name但是如果字符串中有字母以外的非数字字符就会出错,比如将bc4 36 3c5 改为 bc4 3?5。此时如果将检验标准改为判断读入的字符串中是否有非数字以外的字符会更好,
将:
do i=65 to 90;
if index(upcase(temp),byte(i))^=0 then do;
改为:
do i=1 to length(temp);
if substr(temp,i,1)<'0' or substr(temp,i,1)>'9' then do;
二:对于连续数字情况的去除也可以不在本步中进行,输出后name也不清空,即读入一个数据,如果是有非数字字符的就赋值给name,否则给id,如果name,id同时不为空则输出,输出后id 清空,name不清空,再继续读入。对于连续的数字,就会用其前面最近出现name形成多条观测,最后再通过排序只保留每个name对应的第一个观测也可以,这种对应的程序如下:*/ data a;
informat temp $10.;
attrib name informat=$10.format=$https://www.doczj.com/doc/3116506230.html,bel="Name";
attrib id informat=best12.format=best12. lable="Id";
retain name "";/*先将数据流都读入到变量temp中*/
input temp :$10.@@;/*设计一个变量标记temp中的是否有字母,有值为1,否则为0,先设为零*/
flg=0;/*检验temp是否有字母*/
do i=65to90;
if index(upcase(temp),byte(i))^=0then do;/*如果发现一个字母,将flg 变量值改为1,退出循环*/
flg=1;
leave;
end;
/*根据以上的判断,如果temp中有字母,将其赋值给name,如果name不为空,转换为数值型赋值给id*/
if flg=1then do;
name=temp;
end;
else id=input(temp,best12.);
/*如果name和id同时不为空时说明找到了一组配对的数据,输出到数据集中,清空原有的值*/ if name^="" and id^=.then do;
output;
id=.;
end;
keep name id;
cards;
a23 223 bc4 36 3c5 11d 400 620
;
run;
proc sort;
by name;
data a;
set a;
by name;
if https://www.doczj.com/doc/3116506230.html,;
run;
或者
data a(keep=id no);
input x $ @@;
id=lag1(x);
no=input(x,8.);/*把变量x转换成数值,若遇非纯数字的值,则转成缺失值,同时日志窗口NOTE会提示转换无效,不必在意。如果数据很多,可以用系统选项把note去掉:
options nonotes*/
y=lag1(no);
if y='.' and id^=' ' and no^='.';/*选择观测,如果y是缺失值,但id和no不是缺失值,就是我们想要的观测*/
cards;
a23 223 bc4 36 3c5 11d 400 620
;
run;
21.用SAS软件作三维Hat图,x和y轴取值区间为[-5,5],z = sin(sqrt(y*y + x*x))。
data a;
do x=-5to5by0.5;
do y=-5to5by0.5;
z = sin(sqrt(y*y + x*x));
output;
end;
end;
run;
proc g3d;
plot y*x=z;
title'hat graph';
成p=20,q=1的马鞍图形。
提示:产生x, y和z的数据后,用下面的过程实现作图。
proc g3d;
plot y*x=z;
run;
data a;
p=20;
q=1;
do x=-9to9by0.1; /*从-9到9每距离0.1取一个点*/
do y=-3to3by0.1;
z=-x**2/p+y**2/q; /*创建马鞍图的数学公式*/
output;
end;
end;
drop p q;
run;
proc g3d; /*用g3d作图*/
plot y*x=z;
run;
23.数据集Calendar只有日期变量,test包含股票代码、日期与收盘价三个变量。合并两个
数据集,用Calendar中的日期数据替代test数据集中每只股票的日期数据。
创建样本数据集:
data calendar;
input Date yymmdd10.;
format Date yymmdd10.;
cards;
2003-1-20
2003-1-21
2003-1-22
2003-1-23
2003-1-24
2003-1-27
2003-1-28