第十六章SAS数组及其应用•SAS可以把一组同为数值型或同为字符型的变量合在一起,使用同一个名字称呼,用下标来区分。这与通常的程序设计语言中的数组略有区别,通常的程序设计语言中数组元素没有对应的变量名,而SAS数组每个元素都有自己的变量名。一、数值型数组•定义数值型数组的格式为:ARRAY数组名(维数说明)数组元素名列表(初始值表);例如:ARRAYtests(3)mathchineseenglish(0,0,0);•数组名是一个合法的SAS名字且不能与同一数据步中的变量重名。对一维数组,维数说明只要说明元素个数,这时下标从1开始。数组元素名列表列出这个数组的各个元素实际代表的变量名,各变量名以空格分隔。比如,上例中tests(1)代表数学成绩,tests(2)代表语文成绩,tests(3)代表英语成绩。初始值表给各数组元素赋初值,按顺序对应。•数组说明中初始值表可以省略,这时其初始值为相应数组元素的值(如果其数组元素还没有值则初值为缺失值)。数组说明中的数组元素名列表可以省略,这时其元素也有对应的变量名,变量名为数组名后附加序号,比如:ARRAYx(3);中数组x的各元素名为x1,x2,x3。•也可以在说明维数时用“下标下界:下标上界”来说明一个其它的下标下界,如ARRAYsales(95:97)yr95-yr97;这时sales(95)为yr95,sales(96)为yr96,sales(97)为yr97。上面的变量名列表是一种特殊的语法,在用到变量名列表时如果连续写几个前面字母相同,后面是连续的序号的变量,只要写出第一个和最后一个,中间用减号连接。•一维数组的维数说明还可以是一个星号,这时数组大小由提供的元素列表中的变量个数决定,如上面的数组tests可以等价地说明为:ARRAYtests(*)mathchineseenglish(0,0,0);可以用函数DIM(数组名)来获得数组的长度。•可以定义二维数值型数组,只要在维数说明中指定用逗号分开的两个下标界说明,例如:arraytable(2,2)x11x12x21x22;说明table(1,1)为x11,table(1,2)为x12,table(2,1)为x21,table(2,2)为x22。二维数组元素按行排列。二、字符型数组•定义字符型数组的语法略复杂,它需要加一个$符来说明数组元素类型为字符型,并且要说明每一元素所能存储的字符串的最大长度。说明格式如下:ARRAY数组名(维数说明)$元素长度说明数组元素名列表(初始值表);例如:ARRAYnames(3)$10childfathermother;字符型数组其它方面用法与数值型相同。三、临时数组•上面格式说明的数组都是把若干个变量集合在一起使用同一个数组名称呼,每个数组元素是一个独立的变量。SAS也提供了与其它程序设计语言相同的数组,即数组元素只由数组名和序号决定,没有对应的变量名。这种数组叫做临时数组,定义格式为:ARRAY数组名(维数说明)_TEMPORARY_(初始值表);•可见临时数组就是在数组说明中用_TEMPORARY_代替了数组元素列表。例如:ARRAYx(3)_TEMPORARY_(0,0,0);说明了一个有三个元素的临时数组x。其元素为x(1),x(2),x(3),即使变量x1,x2,x3存在也与此数组无关。临时数组的特点是它只用于中间计算,最终不被写入数据集。并且临时数组与其它变量不同的是,它在数据步隐含循环(后面会解释此概念)中能自动保留上一步得到的值。临时数组当然也可以有多维数组,或字符型数组。四、使用数组•临时数组的使用与其它程序设计语言中的数组作用相同,可以存放性质类似的数据进行处理。SAS以变量为元素的数组可以方便变量的循环处理,比如,读入了comp1-comp10十个计算机销售额变量,prin1-prin6六个打印机销售额变量,希望计算其总和,可以用如下的数组说明与DO循环配合进行:datasales;inputcomp1-comp10prin1-prin6;ARRAYy(*)comp1-comp10prin1-prin6;tot=0;doi=1toDIM(y);tot+y(i);end;cards;………;run;•此例中数组说明用了星号说明维数,求总和时用了累加语句。事实上,在数组说明的数组元素列表部分除了列出具体的变量名表外,还可以用特殊名字_NUMERIC_代表所有数值型变量的列表,用_CHARACTER_代表所有字符型变量的列表,用_ALL_代表所有变量的列表(用_ALL_时所有变量应该同为数值型或同为字符型,否则出错)。所以上例中的数组y的说明中还可以用_NUMERIC_或_ALL_代替变量名列表。•实际上,SAS为变量累加提供了一个专门的函数SUM(OF…),比如上面的tot变量可以用SUM(OFcomp1-comp12)计算。这个例子主要为说明如何循环处理多个变量。•变量和变量属性控制语句不是执行语句,可以出现在数据步得任何地方,且结果相同。•显示下表数组语句由数组名,元素个数说明,及元素列表等构成。•数组元素必须全是数值变量,或全是字符变量。•数组元素的两种表示方法:列出变量名,建立临时数组元素列表。•一)显示下标数组语句。•1)直接读(只能读一行)/input语句(可读多行)。dataa;arraytt1-t3;inputt1-t3;cards;123;run;•2)dataa;setresdat.class;arraytt1-t3(1,2,3);run;•3)建立临时数组元素。•使用临时数组元素列表可以少占用内存,加快执行时间。用于定义一个数组的目的只是进行计算时。没开辟新变量,不能出现在输出的数据集上。•引用时必须用数组名和下标,不能用变量。•临时数组元素的值被自动保存而不是像DATA步中的变量,在下一次重复开始时被置为缺失值。•4)arrayt(3)t1-t3(123)#完整定义•araytest(3)(123)#产生新变量test1,test2,test3。•arrayt(5)(123)#正确,t4,t5为缺失值•arrayt(3)t1t2#错误•arrayt(*)(123)#错误arrayab(*)greenreddenato;#里面有三个元素•arrayab(*)_numeric_;#里面有几个数值变量就有几个元素•应用举例:•datax;arrayd(*)_numeric_d1-d3(123);run;•arrayab(*)_character_;#里面有几个字符变量就有几个元素•arrayt(3:4,3:7)test1-test10;#正确•二)显示下标数组元素。•1)一个循DO组里处理多个数组。•dataa;arrayd(*)t1-t4(1234);doi=1todim(d);d(i)=d(i)+10;end;2)dataa;arrayd(*)t1-t4(1234);do_i_=lbound(d)tohbound(d);ifd(_i_)=4thend(_i_)=.;end;run;•3)两维数组。•dataa;arrayx(6:7,0:2)x10-x15;doi=6to7;doj=lbound2(x)tohbound2(x);ifx(i,j)=0thenx(i,j)=.;end;end;inputx10-x15;cards;098765123456;run;•3)DOWHILE和DOUNTIL语句。•dataa;inputx1-x5y;arrayt(5)x1-x5;i=1;dowhile(t(i)y);putt(i)=y=;i=i+1;end;cards;123453024686;run;•一行一行地读,执行完第一行后就从循环里跳出来,执行下一行时i又赋值1。•·改为用隐含下标变量。•dataa;inputx1-x5y;arraytx1-x5;_i_=1;dowhile(ty);putt=y=;_i_=_i_+1;end;cards;123453024686;run;三)隐含下表数组元素。•引用隐含下标数组的元素时,要先设置下标变量,然后在SAS语句中使用数组名字。