跟大家分享一下DATA步中SET语句的一些用法。SET语句在编程中的使用频率是非常高的,可以说几乎没有一段数据处理程序是不用它的,因此很有必要了解它。今天所说的东西大多数人可能都知道,但还有人是不了解的,因此如果你都了解就当作复习吧!
1. 语法介绍
首先了解一下Set语句的语法:
SET <SAS-data-set(s) <(data-set-options(s) )> > <options>;
这里需要注意的就是data-set options是需要用括号括起来,而set语句的options直接跟在数据集名后面,用空格分开即可。常用的data-set options有keep=, drop=, rename=, where=, obs=等。这些option都是非常有用的,而且还会提高程序的运行效率。
SET语句常用的option有end=、nobs=、point=等,这些选项的使用会在后续的实际例子中进行介绍。SET语句可以使用一个数据集或者多个数据集,例如:
set a; set a b; set a1-a10; set a:;
2. END=与NOBS=的使用
END=variable创建一个标志变量,当前观测为数据集的最后一条观测时该变量被赋值1,其他时候都为0;NOBS=variable创建一个变量,其值为当前数据集的总观测数。下面是一个简单的统计程序:
- data null_;
- file print;
- set sashelp.class end=last nobs=tot;
- if age lt 15 then cnt1+1;
- else cnt2+1;
- if last then do;
- pct1=cnt1/tot;
- pct2=cnt2/tot;
- put "小于15岁的人数:" cnt1 ",占总人数的:" pct1 percent8.2;
- put "大于等于15岁的人数:" cnt2 ",占总人数的:" pct2 percent8.2;
- end;
- run;
复制代码
输出结果
3.POINT=选项的使用
Point=variable指定一个变量,该变量的值决定了现在要读入第几条观测,下面是一个例子程序:
有一数据test,其形式如下:(该数据的生成程序见最后附录)
该数据有18条观测,从1到18,每一个数字都对应了一个flag。变量i对应数据sashelp.class中的变量age,现在要做的工作就是通过变量age匹配flag的值。当然这个工作可以用PROC SQL轻松实现,也可以用merge语句实现,但现在要用SET语句加POINT=选项来实现,程序如下:
- data work.test2;
- set sashelp.class;
- temp=age;
- set work.test point=temp;
- run;
复制代码
程序是不是非常简单,比起PROC SQL效率会高很多。尤其在匹配几千万条数据时,PROC SQL的效率是非常低的,因为PROC SQL的运行机制决定了其效率。PROC SQL在做匹配时是先生成两个数据的笛卡尔积存到一个临时表,然后再做匹配。想一想两个一千万数据的笛卡儿积是多么庞大。数据集test2的结果:
4.BY语句的使用
BY语句也是经常用会用到的,尤其在按照某个变量进行分组处理数据时,与其一起使用的是FIRST.variable与LAST.variable。需要注意的是在使用by语句时要保证该数据已经按BY变量排序了,否则会报错。现将sashelp.class数据按照性别、年龄统计身高均值,程序如下:(当然用PROC MEAN是更简单)
- proc sort data=sashelp.class out=test3;
- by sex age;
- run;
- data test4;
- set test3;
- by sex age;
- if first.age then do;
- cnt=0;
- cum_height=0;
- end;
- cnt+1;
- cum_height+height;
- if last.age then do;
- avg_height=cum_height/cnt;
- output;
- end;
- keep sex age cnt avg_height;
- run;
复制代码 数据集test4:
此外,SET+BY也可以对数据集进行排序。数据集data1、data2如下所示:
如果只有SET语句,则结果是这样的:
- data data3;
- set data1 data2;
- run;
复制代码
如果是SET+BY,结果就会是这样:
- data data4;
- set data1 data2;
- by a;
- run;
复制代码
数据集data4已按照变量a进行了排序。注:这样使用的前提是data1和data2已经按照变量a排序了,否则会报错。
5.DO循环加SET语句
利用DO循环和SET语句可以对数据进行取子集,类似于抽样的效果,程序如下所示:
- data test5;
- do i=1 to tot by 3;
- set sashelp.class nobs=tot point=i;
- output;
- end;
- stop;
- run;
复制代码 从sashelp.class数据中抽取了7条观测,结果如下所示:
注:程序中的stop语句是非常重要的,如果没有stop语句则程序会陷入死循环,程序不断地往数据集test5输出数据,直到test5撑爆你的硬盘,系统便提示已没有足够空间。
因为使用了point=选项,SAS无法识别哪一条观测是最后一条,如果没有stop语句,DATA步会一直循环。(理解这段程度的关键在于:搞清楚DATA步自身循环与DO循环,DO循环相当于嵌套在DATA步循环中,好好理解。)
为什么前面在介绍point=选项时的那段程序没有stop语句,也不会引起死循环,这个问题留给你们自己想想吧。。。
两个set语句的使用有时候是非常有效的,即set a; set b;这种形式,加上其他的语句像循环、判断之类的,还有POINT=选项,大家可以多做尝试。
--------------我是分割线----------------
附:test数据集生成程序:
- data work.test;
- do i=1 to 18;
- flag=input(put(64+i,hex2.),$hex2.);
- output;
- end;
- run;
复制代码
|