加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

[转载]SAS语言抛砖引玉·第2章(2)

(2011-11-29 13:56:08)
标签:

转载

分类: 统计学

第二章语言基础
(数组与流程结构)

8.数组(array)
数组是用来临时存放一系列变量的语法结构,常用于需要对一些变量做相同处理的情况。
注意:SAS的数组跟标准语言的数组是不一样,这一点首先要弄明白。在SAS中,数组不是数据结构,它存储的不是数据,而是变量,因此数组元素即是变量,也就是凡是可用表达式的地方,均可使用数组元素;数组只在当前data步中有效,也就是数组名只能在当前data步中标识数组,不同的data步中可以使用相同的数组名但不表示同一个数组;默认情况下,数组的标号是从1开始的。

8.1 数组的定义(definition)
ARRAY array-name { subscript } <$><length> <array-elements> <(initial-value-list)>;
说明:
·数组名的命名规范与变量命名完全相同,不赘述;但是数组名不能与当前data步中变量同名;
·元素个数有三种形式,分别对应于创建数组的三种方法;元素个数必须用大括号({})、中括号([])或圆括号(())括起来,三者等价;
·变量列表必须由相同类型的变量组成,要么全是数值型,要么全是字符型;数组列表同样可以是缩写形式;
定义数组最简单的方法是直接写明元素的个数,如,
array books{3} Reference Usage Introduction;
也可以用上下界来定义元素个数的范围,如
array books{0:2} Reference Usage Introduction;
这样的好处是可以自定义数组第一个元素的标号,上面的例子就是从0开始的,自定义标号某些时候会带来好处,如
array first{10} Year76-Year85;
array second{76:85} Year76-Year85;
数组second显然更方便,不容易引起混淆。
定义数组还可以让系统来计算元素的个数,如
array score{*} score1 score2 score3 score4 score5;
或array score{*} score1-5;
这种定义的方式更多的用于不知道变量个数的情况下,变量的个数就交给SAS去计算把,如,
array x[*] _NUMERIC_;
如果是数组定义一系列字符变量,还可以通过length指定字符变量的长度,如
array ch[*] $ 20 name1-3;

思考题2:那么如果要循环引用这个数组呢,是不是用户还得要知道这个数组有多少个元素?

 

8.2 初始化数组(initial-value)
初始化数组时间上是给数组元素即变量赋值,
ARRAY array-name {number-of-elements} <list-of-variables>(initial-value-1<,…initial-value-n>);
如,array test(3) t1 t2 t3(90 80 70);
array ab(5) (5 4 3);
如果初始值比数组元素少,则初始值依次赋值给变量,多余的变量被处理为缺失值,而且SAS会在LOG窗口中给与WARNING提示。
给数组元素赋值可以采用缩写的形式,如下面5种初始化数组的方法是等价的,
ARRAY x{10} x1-x10 (10*5);
ARRAY x{10} x1-x10 (5*(5 5));
ARRAY x{10} x1-x10 (5 5 3*(5 5) 5 5);
ARRAY x{10} x1-x10 (2*(5 5) 5 5 2*(5 5));
ARRAY x{10} x1-x10 (2*(5 2*(5 5)));

 

8.3 引用数组元素(Array Reference)
语法:array-name {subscript};
不同的引用方式在于数组下标的引用不一样。
·变量作为下标,主要用于循环语句中
{variable-1< , . . . variable-n>}
如,
array days{7} d1-d7;
do i=1 to 7;
if days{i}=99 then days{i}=100;
end;

·*号作为下标{*}
如,
array days{7} d1-d7;
input days {*};

·表达式作为下标
expression-1< , . . . expression-n>
如,
array arr1{*} a1-a3;
x=1;
input a1 a2 arr1{x+2};

·直接使用数组名
见do over array-name循环结构

 

8.4 多维数组(multidimensional array)
定义多维数组跟一维数组没有大多区别,只是不同的维度之间用逗号隔开,同一维度同样可以采用元素个数或上下界的书写方式,但不能用{*}书写方式,如
array x{5,3} score1-score15;
array test{3:4,3:7} test1-test10;
多维数组中,数值元素(即变量)先行后列依次进行填充。引用及初始化数组都跟一维数组一致。

 

8.5 临时数组(_temporary_)
当用户定义一个数组的目的只是进行计算时,经常用临时数组元素列表,使用临时数组元素可以少的占用内存,加快执行速度。
举例,array test{4} _TEMPORARY_ (90 80 70 70);
另外,临时数组还有如下一些特点:
·数组元素没有名字,引用时必须用数组名和下表,如test[1];
·不能出现在输出的数据集上;
·不能用特殊下标(*)来引用所有元素;
·临时数组元素的值总是自动被保存,而不是像普通数组元素在data步的下一次自循环开始时被置为缺失值。

 

8.6 与数组有关的函数
·DIMn(array-name):计算数组第n维的元素个数,第一维时写为DIM,例如:
do i=1 to dim(days);
do i=1 to dim4(days) by 2;
DIMn函数常用于不知道数组元素的情况下,如用{*}创建的数组。
·LBOUNDn(array-name)&HBOUNDn(array-name):计算数组第n维的下届与上届,第一维时省略n,例如:
array years{72:76} first second third fourth fifth;
do i=lbound(years) to hbound(years);
if years{i}=99 then years{i}=.;
end;
这两个函数常用于用上下界形式创建的数组的情况下。

思考题3:为什么数组名与同data步的变量名不能同名?
思考题4:像其他语言一样,数组标号从0开始有什么好处吗?

 

9.流程结构:顺序、选择、循环
程序语言中的流程结构用于控制各计算操作执行的次序。每一种结构化语言编写的程序都由由顺序、选择、循环三种结构构成,SAS也是如此,不同语言之间只是关键字不一样罢了。顺序结构就是指程序执行是按照代码书写的顺序进行的。下面主要讲选择和循环结构。

 

9.1 选择结构
语句一:
IF expression THEN statement;
<ELSE statement;>

语句二:
SELECT <(select-expression)>;
WHEN-1 (when-expression-1 <..., when-expression-n>) statement;
<... WHEN-n (when-expression-1 <..., when-expression-n>) statement;>
<OTHERWISE statement;>
根据它的语法结构发现有两种写法,举例如下
既可以把表达式放在select语句这里,when语句那里只需要选择表达式的值;也可以select语句这里为空,整个选择条件放到when语句中;而不能两种方式混合使用。
方法一
select(x);
when (2) put 'two';
end;
方法二
select;
when (x=2) put 'two';
end;
错误的方法
select (x);
when (x=2) put 'two';
end;
对于select选择结构还有一点要注意的地方,就是select与end之间的程序的执行顺序,这跟其他语言(如C语言)可能有点差别,那就是只要有一个条件满足那么就会跳出选择结构,而不是继续执行下面的语句,这样一来就不需要显性的去跳出选择结构。

 

9.2 循环结构
语句一:
DO WHILE (expression);
...more SAS statements...
END;

语句二:
DO UNTIL (expression);
...more SAS statements...
END;

语句三:
DO index-variable=start <TO stop> <BY increment> <WHILE(expression) | UNTIL(expression)>;
. . . more SAS statements . . .
END;
例如:
do i=1 to 10;
do i='01JAN90'd to '01JAN90'd by 1;
do i=10 to 0 by -1 while(month='JAN');
这个就是常见的步长型循环结构,而且还可以结合While与Until使用来终止循环。那么这里如果do后面什么都不写是否是“无限”循环了呢?留作读者思考。

语句四:
DO item-1<,…item-n><WHILE(expression) | UNTIL(expression)>;
. . . more SAS statements . . .
END;
例如:
do count=2,3,5,7,11,13,17;
do month='JAN','FEB','MAR';
do i='01JAN2001'd,'25FEB2001'd,'18APR2001'd;
这个语句是SAS比较特殊的循环结构,可以对枚举的项目依次执行,终止循环就是执行完这些列举的项目。

语句五:
DO over array-name
. . . more SAS statements . . .
END;
例如:
data test;
    input sc01-sc05;
    array s sc01-sc05;
    do over s;
        s= s*100;
    end;
    cards;
0.95 0.88 0.57 0.90 0.65
;
这个语句也是SAS比较特殊的循环结构,专用于数组,将数组的每一个元素访问一遍。

 

9.3 语句块
DO;
...more SAS statements...
END;
有时候我们需要把很多语句放在一起执行,特别是放在选择结构和循环结构中,这相当于有些语言的一对{}。

 

9.4 如何跳出选择结构和循环体?
continue语句:用于跳出当次循环,重新执行循环体并计算是否满足条件。
leave语句:用于终止循环和选择结构,不再执行循环语句而转到循环语句之后紧接的语句。
return语句:用于跳出当次data步自循环,重新执行data步。
go to语句与标号:用于跳转到指定标号的语句,但该语句要求与当前语句是在同一个data步中。在大多数情况下,使用go to语句的程序段完全可以用do;...end;程序块或者if…else结构来代替,而且使用go to语句会使程序显得复杂、难以理解和维护,所以建议还是少用。但是这个语句既然存在还是有一些用处的,可以用来跳出某些深层嵌套的结构,如跳出多层循环。

0

  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有