本节所用数据集:
链接:https://pan.baidu.com/s/1eHUhVQsvObSGkkNA6lDDlw
提取码:2ce4
一、data步流程
- data语句标志了数据步开始,并指定了数据步结束时要生成的数据集名字。
- 每次读入一行数据,读入后执行数据步中的其他语句,循环数据步读取整个数据。
- _N_变量表示data步已经执行的次数
- _error_变量值为1时表示程序出错
例1:flow
data flow;
/*put x = y = z = _n_;*/
input x y;
z = x + y;
put x= y= z= ;
put _n_= _error_=;
cards;
10 20
100 200
1000 2000
;
run;
-
读外部数据时,数据步迭代(即每一次)的开始把变量的值置为缺失值,有几种情况例外:
(1)retain语句提到的变量;
(2)sum语句中创建的变量;
(3)数组_temporary_中的数据元;
(4)file和infile语句选项中创建的变量;
(5)自动变量 -
读sas数据集时,只在第一次迭代时把变量值置为缺失,以后变量保留其值直至新值写入
二、data语句
- data语句的选项
drop选项:不列出某些变量
keep选项:列出某些变量
label选项:给数据集加标签
rename选项:重命名变量
例2:data
data new1(drop=z); ##删除z变量
set flow;
run;
data new2(keep=x); ##保留x,yz删掉
set flow;
run;
data new3(label='the new3 dataset');
set flow;
run;
data new4(rename=(x=xx,y=yy));
set flow;
run;
proc print data=new1;
run;
proc print data=new2;
run;
- 数据集的名字
(1)data语句后无数据集名字,则自动生成data1,data2等为数据集名字,相当于data_data_;
(2)data_null_;不产生实际的数据集,只是把内容暂存于内存,以供put语句等读取结果,可以节约计算机资源;
(3)data_last_;以最近产生的数据集命名并取代其内容。
(一)文件操作语句
- input语句
(1)分组格式:
input(g1-g5)(37.2,25.2);
input(a b)( 5. ) i n p u t ( a b ) ( 5.) input(a b)( 5.)input(ab)(,5.)
(2)@@-无需分行而按变量连贯读数据
例3:input@@
data;
input x y @@;
cards;
1 2 3 4
;
run;
proc print;
run;
(3)@-固定该数据行;用于需要多个input语句同时读取一行数据
(4)利用@n、+n、#n进行指针控制
(5)几个特殊符号的用法(:& ~)
①:读值时第一次遇到分隔符、或是数据行末尾、或是读满列数而结束
②&字符型输入值可以嵌有一个或几个空格
③~字符型输入值保留引号(与infile语句中选项dsd一起使用才有效)
-
cards语句
(1)cards语句与datalines语句可以通用
(2)如果输入数据中含有分号,可用cards4语句或datalines4语句,同时,数据结尾用4个分号表示数据输入结束 -
put语句
(1)put语句负责在log窗口输出一些结果,file print选项可把输出转移到output窗口
(2)put_infile_(输入最新的数据行到 SAS log 窗口)
(3)put_all_(输入所有变量的值)
(4)put_page_(输出新页) -
file语句
file print把put语句产生的输出结果转移到output窗口 -
by语句
在data步中,SAS系统对每个by组创建两个临时变量:
first.variable
last.variable
它们用来区别每个by组的第一个和最后一个观测 -
set 语句
(1)使用set语句复制数据集
(2)point选项指明要读入的记录序号
set数据集point=指针变量;
可用于抽样,一般与output语句连用
(3)nobs选项创建一个临时变量用来存储数据集的观测总数
(4)set语句可以串接多个数据集,形式如下:
data数据集;
set 数据集A 数据集B ……;
<by 变量;>
run;
(5)rename选项负责改名;in选项产生变量负责记录观测来自该数据集
例4:set
data abc;
set peixun.oranges;
run;
proc print;
run;
例5:point
data zxs;
do n=2 to total;
set sasuser.flow point=n nobs=total;
/*if _error_=1 then abort;*/
output;
end;
stop;
run;
proc print data=zxs;
run;
- merge语句
使用merge语句并接多个数据集,形式如下:
data数据集;
merge数据集1 数据集2 ……;
by 变量;
run;
-
update语句
(1)update语句用一个升级数据集中的观测来修改一个主数据集
(2)update语句一定要与by语句一起使用,by语句给出了合并观测时共同变量的名字
(3)主数据集中的共同变量必须是单值的,即不能有2个或2个以上的观测其共同变量值相同 -
infile 语句
(1)delimiter(DLM)选项:规定一个字符替代空格作为分隔符;
(2)firstobs 选项:不是从文件的第一个记录开始,而是从指定行开始读取记录;
(3)obs 选项:规定用户想从输入文件中连续读取的最后一个记录号
例6:infile(dlm)
data new1;
infile cards delimiter=','; ##delimiter可简写为dlm
input x y z;
cards;
1,2,3
4,5,6
;
data new2;
infile cards dlm='ab'; ##定义 ab 为分隔符,则其任意组合aa、ab、ba、bb也为分隔符
input x y z;
cards;
1aa2ab3
4bb5ba6
7a8b9
;
run;
proc print data=new1;
run;
proc print data=new2;
run;
(4)dsd选项:
①使最外层引号括起的内容当成整个字符串输入,并去除最外层引号;
②默认分隔符为逗号;
③2个相邻的分隔符意味着前一个分隔符后的字段为缺失值
(5)当行末尾数据宽度少于规定宽度时
flowover:默认选项,将下一条记录读入
missover:将变量置为缺失
truncover:将数据直接读入,不管宽度是否少于规定宽度
stopover:系统终止数据步执行,报告出错
例7:missover
data;
infile 'e:\SAS\missover.dat';/*flowover missover truncover stopover pad*/
input x 5.;
run;
proc print;
run;
(6)lrecl=n选项:设定源数据文件行的物理长度,缺省为256,最大可设为32767
(7)pad | nopad 选项:pad 选项指当宽度少于规定宽度时,在后面填充空格至 lrecl=n 规定的行长度,缺省为 nopad
(二)运行语句
- 赋值语句和累加语句
- 赋值 variable = expression
例: x = a + b; - 累加 variable + expression
例:if x = 5 then n + 1;
例:n +(-1) - 累加语句中的变量必须是数值型变量,初始值为0
- delete 和 ostcard 语句
- delete 语句告诉 SAS 系统停止处理当前的观测,并且返回到这个 data 步的开头处理其他观测
- 当 SAS 系统遇到用几个记录表示一个观测的时候,数据中有丢失记录时,使用 lostcard 语句来重新对准输入数据
例8:delete
data jn; ##产生 jn 的临时数据集
input a b c; ##生成 a b c 3个变量
file print;
put _n_; ##数据循环的次数
if a>3 then delete;
*put _n_;
*total = a + b;
cards;
1 2 3
3 3 2
5 3 1
3 3 3
;
proc print;
run;
- stop 和 abort 语句
- 用 stop 语句来停止处理 data 步,正被处理的那个观测没有添加到 SAS 数据集中,stop 语句不影响后面的任意 data 步或 proc 步的执行
- 用 abort 语句来中止 SAS 系统执行当前 data 步,return选项关闭 SAS 并返回操作系统
- stop 与 abort 的区别在于 abort 语句置 error 变量为1
例9:abort
data check;
input ssn 1-3 pay; ##读取 ssn 中的第1-3列数据
if ssn=222 then stop;/*abort return;stop*/
put _all_;
cards;
111 100
222 200
444 300
;
data a;
input b;
cards;
12345
;
proc print data=a;
run;
- where 语句
- 从已存在的 SAS 数据集选择子集,在把观测读入之前规定数据必须满足一个条件
- where 语句与 if 语句相比在读取数据时更为高效,因其在移动所有观测到子集之前先选择数据
- where 语句丰富的表达式
例10:where
data aa;
set sasuser.business;
where employs>50;
*where industry='Food';
*where employs between 50 and 70;
*where employs in (61,62);
*where employs is missing;
*where industry ? 'Ele'; /* ? means 'contains'*/
*where industry like '%t%'; /* % can substitute many char*/
*where industry like '0_1'; /* _ can substitute one char*/
run;
proc print;
run;
- output 语句
- data 步的每次迭代,后台自动使用 output 语句,但如果程序中主动加上 output 语句,即相当于取消自动 output 语句,变成在条件符合时输出
例11:output
data;
input a b;
if a=1 then output;
put _n_;
cards;
2 3
1 5
2 4
1 6
;
run;
proc print;
run;
- 用到 output 语句其他情况:output123例
①从一个输入的数据文件中,创建几个 SAS 数据集
②从输入的每个数据行中,创建2个或更多个观测
③把几个输入观测组合并成为一个观测 - 后面接名字表示输出到指定数据集,但名字必须也在 data 后出现
- call 语句
- 调用其他子程序
call routine (parameter-1 <,…parameter-n>)
如 SAS 提供一系列随机数子程序 - 发布操作系统命令
call system (command)
例12:call
data a;
seed1=161321804;/*赋值随机数种子初始值*/
seed2=135279821;
do i=1 to 5;
x1=ranuni(seed1); ##ranuni均匀分布随机数语句
x2=ranuni(seed2);
output;
end;
proc print;
title '使用随机数函数';
run;
data b;
seed3=161321804;
seed4=936674311;
do i=1 to 5;
call ranuni(seed3,x3);/*seed3存放种子值,x3为随机数变量名*/
call ranuni(seed4,x4);
output;
end;
proc print;
title '调用随机数子程序,产生2个随机数流,并能观测到当前随机数种子值';
run;
(三)控制语句
- do 语句(循环语句)
- do 语句规定,在 do 后面直到出现 end 语句之前的这些语句作为一个单元被执行。
- 简单 do 语句,常用在 if-then/else 语句里
- 循环 do 语句,用下标变量规定重复次数
do i = 1 to 10;
do i = 1 to exit;
do i = 2 to 8 by 2; 即:2 4 6 8
例13:do_simple
data do;
input x;
file print;
if x>5 then do;
y = x * 10;
put x= y= ;
end;
cards;
1
6
7
;
proc print;
run;
例14:do
data a;
input x @@;
do i = 1 to 4;/*把i改成其他字符同样可行*/
y = 4 * x;
output;/*如果略去output,则只输出最后一次循环的结果*/
end;
cards;
11 22 33 44 55 66
;
run;
proc print;
run;
- do while 语句
- 当条件成立时重复执行 do 组里的语句 do while (expression);
- 括号里的表达式在 do 组里的语句被执行前在循环的开头被计算。如果表达式是真的,do 组被执行
例15:do while
data while;
n = 0;
do while (n<4);
file print;
put n = ;
n+1;
end;
run;
- do until 语句
- 有条件地执行 do 组里的语句,在循环的最后而不是在循环的开头计算表达式,如果表达式是真的,do 组就不再被执行
- do 组里的语句至少执行一次
- select 语句
- 允许 SAS 去执行几个语句或者语句组中的一个
- 当一个特殊条件为真时,执行对应when 语句,如果所有 when 条件均不成立,选择执行 otherwise 语句,用 end 结束
例16:select (when)
data old;
input grade $ @@;
cards;
A B1 B2 B3 C D
;
run;
data new;
set old;
x=1000;
select(grade);
when('A') salary=x*1.5;
when('B1','B2','B3') salary=x*1.3;
when('C') salary=x*1.1;
otherwise salary=x;
end;
run;
proc print;
run;
- if 语句
(1)形如:
if expression then statement;
else statement;
(2)形如:
if variable
例:if x then y=x;
当变量x的值为0和缺失之外的任意值时表达式均为真
例17:if_else
data;
input x @@;
if x=1 then y=x;
else if 2<=x<=4 then y=x*10;
else if 5<=x<=7 then y=x*100;
else y=x*1000;
cards;
1 2 3 4 5 6 7 8
;
proc print;
run;
例18:if_x
data aa;
input x @@;
if x then y=x;
cards;
1 0 . 4
;
run;
proc print;
run;
- return 语句
- 告诉 SAS 系统在 data 步当前这个位置上停止执行语句并在继续执行之前返回到一个预定的位置(通常是 data 步开头)
- 当 return 语句使得 SAS 返回到 data 步开头时, SAS 首先输出当前观测到新数据集中
- 每个 data 步都有一个隐含的 return 语句作为最后一个可执行的语句
- go to 语句
- 告诉 SAS 系统立即转到 go to 语句所指示的那个语句,并从那个语句开始执行后面的语句
- 形如:GO TO label;
label 规定语句标号来指示 go to 的目标,它必须与 go to 语句在同一个 data 步 - return 选项规定返回而不执行下面语句
例19:go to
data info;
input x @@;
file print;
if 1<=x<=5 then goto ok;
put x;/*不是属于if的执行*/
count+1;/*不是属于if的执行*/
*return;
ok:y+x;/*这句一直要执行*/
cards;
7 2 16 5 323 1 11
;
proc print;
run;
- link 语句
- 形如link label;
- 立即转到由 label 语句指示的位置,并从那里开始继续执行语句直到一个 return 语句被执行
- 与 goto 语句的区别是:标签内的 return 语句让 SAS 立即返回到 link 语句后面的那个语句并从那里继续执行
- continue 和 leave 语句
- continue 语句使得某个 do 循环中当前这次循环过程停止进行,并继续进行下一次循环过程
- leave 语句停止当前整个 do 组循环或 select 组的处理过程,并用跟在 do 组或 select 组后面的下一个语句继续执行 data 步
例20:continue
data zzz;
*drop i;
do i=1 to 5;
input name $ idno status $;
if status='PT' then continue;
input benefits $10.;
output;
end;
cards;
Jones 9011 PT
Thomas 876 PT
Richards 1002 FT
Eye/Dental
Kelly 85111 PT
Smith 433 FT
HMO
;
proc print;
run;
例21:leave
data week;
input name $ idno start;
bonus=0;
do year=start to 1991;/*from start to year add 50 every year*/
if bonus ge 500 then leave;
bonus+50;/*如果在 do 循环里是类似累加,循环进行到exit+1*/
end;
cards;
Jones 9011 1990
Thomas 876 1976
Barnes 7899 1991
Harrell 1250 1975
Richards 1005 1990
Kelly 85 1981
Stone 091 1990
;
proc print;
run;
-
循环的嵌套
-
总结:怎样选择使用不同的控制语句
(1)do:多次执行同样的代码块
(2)do while:当 while 条件为真时,多次执行同样的代码块
(3)do until:多次执行同样的代码块,直到 until 条件为真,代码块总会执行一次
(4)select:知道明确的离散选择项时使用
(5)if:希望从2个或多个可能的事件中完成一个,允许连续选择项
(6)跳转代码(go to, link):需要暂停主代码,执行“标签”指明的其他代码
(7)中止代码(return, continue, leave):负责某种形式的中止
(四)信息语句
- 数组语句(array 语句)
当需要用同一种方法处理很多变量时,可以用数组语句定义这组变量为某个数组中的元素
(1)显示下标 array 语句:由一个数组名字,在数组中元素个数的说明,及元素列表组成
- 形如:
ARRAY array-name {subscript} <$>
<<(initial-values)>> - 例
array simple{3} red green yellow;
array x{5,3} score1-score15;
array c{3} 等价于 array c{3} c1-c3
array test{3} t1 t2 t3 (90 80 70) - 数组中的变量必须全是数值型或字符串型
例22:array
data;
array x{3} a b c (1 2 3);
file print;
put x{1}= x{2}= x{3}=;
run;
data;
array x{2,3} aa bb cc dd ee ff(1 2 3 4 5 6);
file print;
put x{2,1}=;
run;
data;
array x{2}$ aaa bbb('data' 'process');
file print;
put x{2}=;
run;
data;
array x{6:9,0:9} x60-x99;
file print;
put x{7,0};
run;
- 规定数组中每一维的上下界:array x{1:5,1:3} score1-score15;
- {*} 表示 SAS 系统通过数组中变量的个数来确定下标。可用 dim(数组名)函数计算数组元素个数
- temporary 建立一个临时数组元素列表
例23:array(dim)
data zz;
input d1-d7;
array day(*) d1-d7;
do i=1 to dim(day);
day(i)=day(i)+10;
end;
drop i;
cards;
99 11 22 222 22 3 44
1 2 3 4 5 6 7
;
run;
proc print;
run;
(2)隐含下标 array 语句:由一个数组名字、一个下标变量和列表名组成
- 形如:ARRAY array-name <(index-variable)><$> array-elements <(initial-values)>
- 如果没有规定下标变量, SAS 系统使用自动变量 i 作为下标变量,下标变量范围从1到这个数组元素的个数
- 如:array x x1-x5
例24:array(s)
data test;
input sco1-sco5;
array s sco1-sco5;
do _i_ =1 to 5;
s = s*100;
end;
cards;
0.95 0.88 0.57 0.90 0.65
1 2 3 4 5
;
run;
proc print;
run;
- do over 语句
- do over 语句对每个数组元素自动地执行 do 组中的语句,它等价于 do i =1 to k;其中 i 是这个数组的下标变量,k是数组元素的个数
- do over 语句常用在对隐含下标数组元素执行 do 组里的语句
例25:do over
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
1 2 3 4 5
;
proc print;
run;
- informat 语句
- informat 语句把输入格式与变量联系起来,在 data 步,可以用 informat 语句对 input 语句中列出的变量规定缺省时的输入格式
例26:informat
data infex;
informat default=3.1 default=$char4. x1 2.2;
/*数值的输入格式忽略w.d格式中w的值*/
input x1-x5 name $;
file print;
put x1-x5 name;
cards;
1111 22 33 4444 100 Johnny
;
run;
- format 语句
- 在 data 步把变量同输出格式联系起来
- 可以规定缺省选项,如:format default=8.2;
- drop 和 keep 语句
- drop 语句:删掉变量语句
drop variable-list - keep 语句:保留变量语句
keep variable-list - 虽然出现在 drop 和 keep 语句中的变量不包含在正被创建的 SAS 数据集中,但这些变量仍可以用在程序语句中
- retain 语句
- 使用 retain 给变量赋予初始值,并保留到读下一个观测
retain month1-month5 1
retain var1-var4(1,2,3,4) - 当 retain 后无变量时,用 input 或赋值语句创建的所有变量的值,保留上次 data 步执行的值
- attrib 语句
- 在 data 步内允许使用一个 attrib 语句来规定一个或几个变量的输出、输入格式,标签和长度,即规定变量属性
- Attrib x label=‘中国载人飞船’
length=4
informat=8.5
format=8.2;
- window 语句
- 创建用户专用的窗口,可用来显示文字说明或接受输入的数据
例27:window
data _null_;
window start ##窗口名为start
#5 @26 'welcome to the sas system' color=yellow ##移到第5行低26列
#7 @19 'this program creates two sas data sets'
#8 @26 'and use three procedures'
#12 @27 'press enter to continue';
display start;
stop;
run;