null第9章 数据步变量与变量属性控制第9章 数据步变量与变量属性控制清华大学经管学院 朱世武
Zhushw@sem.tsinghua.edu.cn
Resdat
样本
保单样本pdf木马病毒样本下载上虞风机样本下载直线导轨样本下载电脑病毒样本下载
数据:www.resset.cn
SAS论坛: www.resset.cn本章内容本章内容本章介绍利用数据步变量与信息控制语句进行数据加工整理。
数据步变量与信息控制语句规定数据集中变量个数及相关信息。变量与信息控制语句不是执行语句,可以出现数据步的任何地方,且功能相同。 ARRAY语句 ARRAY语句 ARRAY语句用于定义数组。数组通常由一组变量构成。
利用数组可以简化很多复杂的数据处理过程。
SAS系统引用数组等价引用构成数组的那一组变量。 显式下标数组语句 显式下标数组语句 显式下标数组由数组名,元素个数说明,及元素列表等构成。
通过数组名引用整个数组,通过数组元素序号(也称为下标)引用该元素。
语句格式
ARRAY array-name{subscript}<$>
<<(initial-values)>>;
选项说明: 下标的三种格式 下标的三种格式 下标用于表示数组中元素的个数和排列的范围。括号可用大括号,中括号或圆括号。
下标格式有三种: null例9.1 用格式一定义一维、二维数组。
Array simple{3} red, green, yellow; /*定义一维数组 */
例中,数组名为simple,数组有三个元素,对应的变量命名分别为red, green, yellow.
Array x{5,3}scorel-score15; /*定义二维数组 */
例中,数组名为X,15个变量scorel---score15按顺序从左上角开始逐行放入这个二维数组。
例9.2 用格式二定义二维数组。
Array x{1:5,1:3}scorel-score15;
当用1作为数组下界时可以省略。
注意:用0作为下界时,可以加快处理时间,因为计算下标的时间减少了。 数组元素表示方法 数组元素表示方法 数组元素必须全是数值变量,或全是字符变量,可以用任意顺序列出。
数组元素的两种表示方法:
列出变量名;
建立临时数组元素列表。
例9.3 列出变量名。
Array C{3} Cl-C3;
Array C{3}; /*和上例句等价 */
Array A{*} _NUMERIC_ ;
Array A{*} _CHARACTER_;建立临时数组元素列表: 建立临时数组元素列表: _TEMPORARY_;
使用临时数组元素列表可以少占用内存,加快执行时间。
可以像使用DATA步中变量那样使用临时数组元素,但要注意有下面几点不同:
它们没有名字,引用时必须用数组名和下标;
不能出现在输出的数据集上;
不能用特殊下标(*)来引用所有元素;
临时数组元素的值被自动保存,而不是像DATA步中的变量,在下一次重复开始时被置为缺失值。 null例9.4 建立临时数组元素。
若用如下程序,则会产生新变量t1,t2,t3;
data a;
set ResDat.class;
array t(3) (5,10,15);
run;
若用临时数组,则不会产生新变量
data a;
set ResDat.class;
array t(3) _temporary_ (5,10,15);
run;null使用临时数组不用临时数组初始值表示方法 初始值表示方法 例9.5 数组元素和初值通过对应位置来确定。
array test (3) t1 t2 t3 (90 80 70);
array ab(5) (5 4 3);
例中,第一个语句数组元素的个数与初值的个数相同,把初值90,80和70依次赋给变量t1,t1和t3。第二个语句分配5给ab1,4给ab2,3给ab3,因数组元素比给出的初始值多,多余的变量ab4和ab5为缺失值,而且SAS系统将发布一个警告信息。 应用举例 应用举例 例9.6 定义数组例句。
array rain{5} x1-x5;
array ab(*)x y z;
array x[*]_numeric_;
array test(3)_temporary_(90 80 70);
array days{7} d1-d7;
array x{2:5}green red denato fetzer;
array test (3:4,3:7) test1-test10;引用显式下标数组元素 引用显式下标数组元素 凡是可用表达式的地方,都可以使用数组元素。
例9.7 通过下标引用数组元素。
data new;
input qa1-qa10 qb1-qb10;
array test{10} qa1-qa5 qb1-qb5;
put test{4}= test{6}=;
cards;
1 1 1 6 1 1 1 1 1 1 8 2 2 2 2 2 2 2 2 2
;
例中,输出qa1和qb1的值,即数组元素test(4)引用qa4, 数组元素test(6)引用qb1.
一个数组的定义仅在当前的DATA步有效。如果想在几个DATA步引用同一个数组,必须在每个DATA步中都定义这个数组。 null455 data new;
456 input qa1-qa10 qb1-qb10;
457 array test{10} qa1-qa5 qb1-qb5;
458 put test{4}= test{6}=;
459 cards;
qa4=6 qb1=8
NOTE: 数据集 WORK.NEW 有 1 个观测和 20 个变量。
NOTE: “DATA 语句”所用时间(总处理时间):
实际时间 0.01 秒
CPU 时间 0.01 秒
461 ;循环DO组中引用 循环DO组中引用 例9.9 规定数组的一些特殊元素作为循环DO语句范围。
array day(7) d1-d7;
do i=2 to 4;
do i=1 to 7 by 2;
do i=1,3;
例中,处理数组DAY中选定的一些特殊元素。 null例9.10 一个循环DO组里处理多个数组。
array day(*)d1-d4;
do i=1 to dim(day);
day(i)=day(i)+10;
end;
例中,循环DO语句里使用DIM函数得到数组中元素的个数。用DIM函数作为DO语句上界时,这个上界会根据数组元素个数的实际情况自动调整,用DIM函数作为DO语句上界的所有语句都不必改动。 null例9.10 引用规定上下界的一维数组。
Array yrs{76:85} year76-year85;
do i=76 to 85 ;
if yrs(i)=9 then yrs(i)=.;
end;
do i=lbound(yrs) to hbound(yrs);
if yrs(i)=9 then yrs(i)=.;
end;
例中,两个DO组是等价的。第二个DO组中LBOUND函数取数组YRS的下界,而HBOUND函数取YRS的上界。 DO WHILE和DO UNTIL组引用 DO WHILE和DO UNTIL组引用 使用DO WHILE或DO UNTIL语句处理数组时,首先要创造循环变量,然后利用数组说明实现DO WHILE或DO UNTIL语句的条件,最后使用程序语句来改变循环变量的值。
null例9.13 DO WHILE语句用法。
data test;
input x1-x5 y;
array t(5) x1-x5;
i=1;
do while (t(i)<$>
Array-elements <(initial-values)>;
选项说明: null例9.14 定义字符数组。
data a;
input x1 $3.x2 $3.;
array item(j)$ 12 x1-x10;
例中,定义字符数组ITEM,前两个元素x1和 x2,长度为3,它们在INPUT语句里定义了。其它8个元素在ARRAY语句里用长度说明选项,给出长度为12。 null例9.15 规定组成数组的元素。
Input (x1-x3) ($8.) x4 x5;
Array item _character_;
例中,INPUT语句用输入格式$8.读字符变量x1至x3,而x4和x5是数值变量。ARRAY语句使用特殊变量_character_只能引入字符变量到数组中。
一个变量或一个隐含下标数组可以是多个隐含数组的元素。 引用隐含数组元素 引用隐含数组元素 例9.16 引用隐含下标数组的元素时,要先设置下标变量,然后在SAS语句中使用数组名字。
data a;
input id x1-x10 y1-y10;
array big(i) x1-x10 y1-y10;
i=11;
put big;
cards;
9155 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2
;
例中,输出隐含数组BIG中的第11个元素值。 null504 data a;
505 input id x1-x10 y1-y10;
506 array big(i) x1-x10 y1-y10;
507 i=11;
508 put big;
509 cards;
2
NOTE: 数据集 WORK.A 有 1 个观测和 22 个变量。
NOTE: “DATA 语句”所用时间(总处理时间):
实际时间 0.01 秒
CPU 时间 0.01 秒
511 ;
null例9.17 循环DO组中引用。
data test;
input s1-s5;
array s s1-s5; /* array语句里没有规定下标变量 */
do _i_=1 to 5; /* 使用自动变量_i_作为下标变量 */
s=s*100;
end;
cards;
.95 .88 .57 .90 .65
.95 .88 .57 .90 .65
.95 .88 .57 .90 .65
.95 .88 .57 .90 .65
;
run;
例中,s1到s5中的每个变量值都乘以100.
null例9.18 DO OVER组中引用。
data two;
input id x1-x10 y1-y10;
array big(i) x1-x10 y1-y10;
do over big; /*等价于do I=1 to 20;其中20是big中元素的个数。*/
if big=. Then big=0;
end;
cards;
例中,将数组BIG中的所有缺失值改为0。 null例9.21 使用一些数组作为另一些数组的元素。
data a;
array test1 t1q1-t1q10;
array test2 t2q1-t2q10;
array test3 t3q1-t3q10;
array ans(k) test1-test3;
input t1q1-t1q10 t2q1-t2q10 t3q1-t3q10;
do k=1 to 3;
do j=1 to 10;
if ans=. then ans=0;
end;
end;
cards;
例中,有一组数据,包括三组测验
题
快递公司问题件快递公司问题件货款处理关于圆的周长面积重点题型关于解方程组的题及答案关于南海问题
,每组又有十个问题。每个学生的测验数据包括30个答案。在DATA步使用ARRAY语句可以把这30个答案中的缺失值改变为0.
null例9.22 使用DO OVER语句处理上例。
do over ans;
do over test1;
if ans=. Then ans=0;
end;
end;
由于test1, test2, test3维数相同,在内层do over语句中规定的数组名可以是这三个数组名的任一个。
只有当嵌套的DO OVER语句引用的每个数组定义不同的下标变量时才能使用嵌套DO OVER语句。 INFORMAT语句 INFORMAT语句 INFORMAT语句把输入格式与变量联系起来。
语句格式:
INFORMAT variables ;
选项说明:
选项DEFAULT=可以出现在INFORMAT语句中的任何位置,仅适用于当前的DATA步。
没有规定临时的缺省输入格式时,使用SAS系统规定的缺省输入格式。 null例9.23 规定临时的缺省输入格式。
data a;
informat default=3.1 default=$char4.;
input x1-x5 name $;
put x1-x5 name;
cards;
11 22 33 44 100 johnny
;
run;
程序提交后LOG窗口输出显示:
1.1 2.2 3.3 4.4 10 John
例中,在INPUT语句列出的变量X1-X5和NAME没有规定输入格式,那么使用这里规定的缺省输入格式,即用格式3.1输入X1-X5,用格式$char4.输入NAME.
null例9.23 取消已存在的输入格式。
data a;
set ResDat.idx000001;
informat date;
run;
例中,删除变量DATE的输入格式。这里INFORMAT和SET语句的次序是重要的。 nullFORMAT语句 FORMAT语句 语句格式:
FORMAT variables ;
选项说明:
选项DEFAULT=可以出现在FORMAT语句中的任何位置,仅适用于当前的DATA步。
没有规定临时的缺省输出格式时,使用SAS系统规定的缺省输入格式。 null例9.25 规定临时的缺省输出格式。
data ;
format w $ 3. y 10.3 default=8.2 default=$8.;
w='good morning.';
x='good morning.';
y=12.1;
z=12.1;
put w/x/y/z;
run;
程序提交后LOG窗口输出:
goo
good mor
12.100
12.10
null例9.27 规定日期时间变量的输出格式。
data a;
input name $ bdate date7.;
format bdate worddate.;
cards;
jimmy 15jan84
cindy 03mar85
;
proc print;
run;
如果没有FORMAT语句,表示日期变量date的值将用1960年1月1日和日期值之间的天数输出。
因此,对于SAS日期时间值变量,必须用FORMAT语句对变量指定相应的日期时间输出格式,这样才能便于理解。 nullObs name bdate
1 jimmy January 15, 1984
2 cindy March 3, 1985LENGTH语句 LENGTH语句 LENGTH语句用于规定存贮变量值的字节长度。
语句格式
LENGTH>
;
其中:
variable-specification变量说明项;
DEFAULT=n规定新创建数值变量值的缺省字节长度从8改为n值。 variable-specification选项的格式 variable-specification选项的格式 变量说明项格式:
variable-1<…variable-n><$>length
相关选项说明: 控制变量长度方法 控制变量长度方法 用LENGTH语句或ATTRIB语句都可以指定变量的长度。
任意一个用LENGTH语句规定的长度可以用ATTRIB语句改变它,反之亦然。
变量的长度依赖于:
是数值还是字符变量;
变量是如何创建的;
有没有LENGTH或ATTRIB语句。 数值变量长度控制 数值变量长度控制 在SAS数据集中数值变量的存贮长度一般为8个字节(byte)。然而很多值可以用小于8个字节的长度准确地表示。当数据集很大时,使用小于8个字节长度来存贮不需要很精确的值时,可以有效地减少外部存贮的要求。
注意:用LENGTH语句截短数据时,可能会引起误差。 null例9.28 截短数据引起的误差问题。
data one;
input a 1-4 b 6.;
length default=3;
cards;
1.4 6
1.2 5
1.1 4
1.3 4
1.3 5
1.3 6
2.0 3
;
data two;
set one;
if a=1.3;
run;
例中,数据集TWO中没有观测。因为,第二个DATA步的子集IF语句中的常数1.3用8个字节表示, 而数据集ONE中变量A按LENGTH语句规定只有3个字节, 因此A不会等于1.3.字符变量长度控制 字符变量长度控制 如果不用LENGTH或ATTRIB语句规定变量的长度,字符变量的缺省长由它的第一个观测值决定,这样,后面更长的观测值会被截短。
因INPUT语句可隐含地说明字符变量的长度。所以,当LENGTH语句定义的字符长度不同于在INPUT语句中隐含表示的长度时,LENGTH语句应放在INPUT语句前面。 null例9.29 LENGTH语句必须放在INPUT语句前面才能起作用。
data a;
length name $20;
input name $1-10;
cards;
(数据行)
;
run;
例中,INPUT语句隐含指定变量NAME的长度为10。LENGTH语句(放在INPUT语句前面)给出在创建的数据集A中NAME的长度用20替代10。
null例9.30 字符变量的长由它的第一个观测值决定。
data b;
input x;
if x=1 then y='no';
else y='yes';
Cards;
1
5
;
run;
例中,字符变量Y第一次在赋值语句Y='NO'中出现时,它的长度被确定为2。于是,当把'YES'赋给Y时,仅前两个字符被存储,'S'丢失了。为解决该问题,或者使用LENGTH语句规定Y的长度,或者重新排列语句顺序。 LENGTH语句位置的重要性 LENGTH语句位置的重要性 改变字符变量的长度时,LENGTH语句必须放在SET语句的前面;
改变数值变量的长度时,LENGTH语句可以放在任何地方。 null例9.30 SET语句之后的LENGTH语句对字符变量不起作用。
data a;
lstknm=’深发展’;
data b;
lstknm=’大秦铁路’;
data c;
set a b;
length lstknm $12 ;
proc print;
run;
例中,length语句放在set语句之后不起作用,lstknm的长度为6,所以显示的值分别为’深发展’和’大秦铁’ 。 Obs lstknm
1 深发展
2 大秦铁null上段程序的正确写法:
data a;
lstknm=’深发展’;
data b;
lstknm=’大秦铁路’;
data c;
length lstknm $12 ; /*length语句放在set语句之前 */
set a b;
proc print; /*显示正确结果 */
run; Obs lstknm
1 深发展
2 大秦铁路LABEL语句 LABEL语句 LABEL语句用于为变量加标签。变量标签是对变量的进一步说明,看到标签就能理解变量的意思。这个标签在SAS数据集中同变量名一起被存贮,而且可通过许多SAS过程被打印输出。
语句格式:
LABEL variable-1='label-1' …;
其中:
Variable规定加标签的变量名;
Label规定最多40个字符的标签。
一个标签语句可以出现若干个变量名和标签。
null例9.32 Label语句的两种写法。
第一种写法:
Label
scode="交易所用代码|stock code by exchange"
hstocd="最新股票代码|stock code"
shrsdt="观测日|shares outstanding observation date"
shrout="观测到的b股股本|b shares outstanding";
第二种写法:
label scode="交易所用代码|stock code by exchange"
label hstocd="最新股票代码|stock code"
label shrsdt="观测日|shares outstanding observation date"
label shrout="观测到的b股股本|b shares outstanding";
例9.33 删除变量的标签。
Label scode='' hstocd='' shrsdt='' shrout='';
ATTRIB语句 ATTRIB语句 ATTARIB语句用于规定多个变量的输出格式,输入格式,标签和长度。
语句格式
ATTRIB variable-list-1 attribute-list-1
<…variable-list-n attribute-list-n>;
其中:
variable-list规定要定义属性的变量列表;
attribute-list规定变量属性列表。
可以规定的变量属性 可以规定的变量属性 ATTRIB语句可以规定的变量属性有:
FORMAT=format规定输出格式;
INFORMAT=informat规定输入格式;
LABEL='label'规定标签;
LENGTH=<$>length规定长度。字符变量前面加$。
ATTRIB语句永久地为变量规定了属性。可以用FORMAT,INFORMAT,LABEL,和LENGTH语句来指定变量的属性。
用ATTRIB语句指定的任何属性都可以用多个属性的语句改变它,反之亦然。 应用举例 应用举例 例9.34 对单个变量定义一种属性。
attrib scode length=$6;
例9.35 对单个变量定义多种属性。
attrib date informat=mmddyy. Format=worddate.;
例9.36 对多个变量定义相同的多种属性。
attrib S1 S2 S3 length=$4 label='SCORE';
例9.37 对多个变量定义不同的多种属性。
attrib S length=$ 4 label='SCORE' date informat=mmddyy.
Format=worddate. label='TEST DATE';
例9.38 对变量列表定义一种属性。
attrib month1-month12 label='MONTHLY SALES';
变量后面几种属性选项的次序是任意的。 DROP语句 DROP语句 DROP语句规定输出数据集中要删除的变量,它对DATA步正在创建的所有SAS数据集都适用。
语句格式:
DROP variable-list;
其中:
varible-list规定输出数据集中要删除的变量。 null例9.39 Drop语句与数据集中的drop=选项 。
data a;
set ResDat.class;
drop sex age; /* drop语句 */
proc print;
run;
data a (drop=sex age); /* 数据集中的drop=选项 */
set ResDat.class;
proc print;
run;
例中,两段程序的效果相同。DROP语句告诉SAS系统新建数据集A中将删除SEX 和AGE两个变量。 KEEP语句 KEEP语句 KEEP语句规定输出数据中要保留的变量,它对DATA步正在创建的所有SAS数据集都适用。
语句格式:
KEEP variable-list;
其中:
variable-list规定输出数据集中要保留的变量。 null例9.40 Keep语句与数据集中的keep=选项 。
data a;
set ResDat.idx000001;
keep date clpr; /* keep语句 */
proc print data=a (obs=10);
run;
data a (keep=date clpr); /* 数据集中的keep=选项 */
set ResDat.idx000001;
proc print data=a (obs=10);
run;DROP和KEEP语句使用规则 DROP和KEEP语句使用规则 同一个DATA步不用同时使用DROP和KEEP语句;
RENAME语句和KEEP或DROP语句一起使用时,KEEP语句和DROP语句会首先起作用。即,在KEEP语句或DROP语句中使用是旧名字。
null例9.41 RENAME语句和KEEP语句一起使用时,KEEP语句使用旧变量名时程序运行正常,keep语句使用新变量名时程序运行出错。
data a;
set ResDat.Idx000001;
keep date clpr; /* 使用旧变量名,程序运行正常 */
rename clpr=clpr_SH;
run;
data a;
set ResDat.Idx000001;
keep date clpr_SH; /* 使用新变量名,程序不能正常运行 */
rename clpr=clpr_SH;
run;数据集选项DROP=和KEEP=使用规则 数据集选项DROP=和KEEP=使用规则 数据集选项drop=和keep=的使用规则基本同drop和keep语句的使用规则。但更灵活,实现同样的功能,对于不同的数据集,新旧名的使用规则也不同 。RENAME语句 RENAME语句 RENAME语句可以更改多个变量的名字。
语句格式:
RENAME old-name-1=new-name-1… ;
其中:
old-name规定输入数据集中出现的变量名字;
new-name规定变量的新名字。
由于变量的新名字在输出的数据集中才起作用,所以,在当前DATA步的程序语句须使用老名字。
null例9.45 应用举例。
data a (keep=date open low high close);
set ResDat.Idx000001;
rename oppr=open lopr=low hipr=high clpr=close;
proc print data=a (obs=3);
run;RETAIN语句 RETAIN语句 RETAIN语句来规定单个变量,变量列表,或数组元素的初始值。
语句格式:
RETAIN
<…element-list-n>>;
选项说明:
null例9.46 没有选项时,规定用INPUT语句或赋值语句创建的所有变量值从DATA步的这次执行到下一次重复时被保留。于是数据值在一些观测中可能保留了本应为缺失值的其它值。
data a;
input id @@;
retain;
if id=1 then test='pass';
if id=2 then test='fail';
cards;
1 2 2 2 3 5 1 5 3 1
;
proc print noobs;
run;null打印输出结果为:
例中,当ID的值为1或2时,都是对的。但当ID等于1和2以外的值时,没有一个IF条件是真的,故TEST没有接收新的值。由于有RETAIN语句,所以,TEST就保持从上一观测中得到的值,这样就产生错误。若从这段程序删除RETAIN语句,当ID值不等于1或2时TEST的值为空格(缺失值).
nulldata a; 打印输出结果为:
input id @@;
if id=1 then test='pass';
if id=2 then test='fail';
cards;
1 2 2 2 3 5 1 5 3 1
;
proc print noobs;
run;
用_ALL_, _CHAR_或_NUMERIC_规定变量列表时,只有在RETAIN语句之前定义的变量才有效。