SAS中文论坛

 找回密码
 立即注册

扫一扫,访问微社区

查看: 4553|回复: 1
打印 上一主题 下一主题

About Set Statement

[复制链接]

10

主题

39

帖子

1075

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1075
QQ
跳转到指定楼层
楼主
发表于 2014-2-22 20:37:21 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
跟大家分享一下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创建一个变量,其值为当前数据集的总观测数。下面是一个简单的统计程序:
  1. data null_;
  2.      file print;
  3.      set sashelp.class end=last nobs=tot;
  4.      if age lt 15 then cnt1+1;
  5.      else cnt2+1;
  6.      if last then do;
  7.            pct1=cnt1/tot;
  8.            pct2=cnt2/tot;
  9.            put "小于15岁的人数:" cnt1 ",占总人数的:" pct1 percent8.2;
  10.            put "大于等于15岁的人数:" cnt2 ",占总人数的:" pct2 percent8.2;
  11.      end;
  12. run;
复制代码


输出结果


3.POINT=选项的使用
Point=variable指定一个变量,该变量的值决定了现在要读入第几条观测,下面是一个例子程序:

有一数据test,其形式如下:(该数据的生成程序见最后附录)


该数据有18条观测,从1到18,每一个数字都对应了一个flag。变量i对应数据sashelp.class中的变量age,现在要做的工作就是通过变量age匹配flag的值。当然这个工作可以用PROC SQL轻松实现,也可以用merge语句实现,但现在要用SET语句加POINT=选项来实现,程序如下:

  1. data work.test2;
  2.      set sashelp.class;
  3.      temp=age;
  4.      set work.test point=temp;
  5. run;
复制代码

程序是不是非常简单,比起PROC SQL效率会高很多。尤其在匹配几千万条数据时,PROC SQL的效率是非常低的,因为PROC SQL的运行机制决定了其效率。PROC SQL在做匹配时是先生成两个数据的笛卡尔积存到一个临时表,然后再做匹配。想一想两个一千万数据的笛卡儿积是多么庞大。数据集test2的结果:




4.BY语句的使用

BY语句也是经常用会用到的,尤其在按照某个变量进行分组处理数据时,与其一起使用的是FIRST.variable与LAST.variable。需要注意的是在使用by语句时要保证该数据已经按BY变量排序了,否则会报错。现将sashelp.class数据按照性别、年龄统计身高均值,程序如下:(当然用PROC MEAN是更简单)

  1. proc sort data=sashelp.class out=test3;
  2.      by sex age;
  3. run;
  4. data test4;
  5.      set test3;
  6.      by sex age;
  7.      if first.age then do;
  8.            cnt=0;
  9.            cum_height=0;
  10.      end;
  11.      cnt+1;
  12.      cum_height+height;
  13.      if last.age then do;
  14.            avg_height=cum_height/cnt;
  15.            output;
  16.      end;
  17.      keep sex age cnt avg_height;
  18. run;
复制代码
数据集test4




此外,SET+BY也可以对数据集进行排序。数据集data1data2如下所示:



如果只有SET语句,则结果是这样的:
  1. data data3;
  2.      set data1 data2;
  3. run;
复制代码


如果是SET+BY,结果就会是这样:
  1. data data4;
  2.      set data1 data2;
  3.      by a;
  4. run;
复制代码


数据集data4已按照变量a进行了排序。注:这样使用的前提是data1data2已经按照变量a排序了,否则会报错


5.DO循环加SET语句
利用DO循环和SET语句可以对数据进行取子集,类似于抽样的效果,程序如下所示:
  1. data test5;
  2.    do i=1 to tot by 3;
  3.       set sashelp.class nobs=tot point=i;
  4.       output;
  5.    end;
  6.    stop;
  7. 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数据集生成程序:
  1. data work.test;
  2.      do i=1 to 18;
  3.            flag=input(put(64+i,hex2.),$hex2.);
  4.            output;
  5.      end;
  6. run;
复制代码


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
分享到:  微信微信
收藏收藏1
回复

使用道具 举报

1

主题

13

帖子

54

积分

注册会员

Rank: 2

积分
54
沙发
发表于 2014-12-12 16:21:26 | 只看该作者
非常好的东东啊!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|手机版|Archiver|SAS中文论坛  

GMT+8, 2024-12-22 14:22 , Processed in 0.130207 second(s), 23 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表