跟大家分享一下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;
 
  复制代码 
 
 |