1、The little SAS book 学习笔记第三章 开发你的数据3.1 创建并重新定义变量可以通过分配语句来创建并重新定义变量,基本形式为:Variable=expressionVariable 是变量名,expression 可以是常量、其他变量、或者数学表达式。分配语句的基本类型有:Expression 是数学表达式时,需要遵循运算法则,先算指数、再算乘除、之后是加减。可以用括号改变运算等级。例子 如下是一个农产品估重数据,每位农民要求对他们的番茄、南瓜、豌豆、葡萄进行估重:下面代码从 garden.dat 原始文件中读取数据,并进行修改:这个程序包含了 5 句分配语句,第一个将 14
2、 赋值给 zone,第二个使 type 等于一个字符串常量打印出的结果中,既包括旧变量,又包括新变量:由于观测值 susan 的 peas 变量出现了缺失值,因此这个观测值的 total 和 pertom 变量也出现了缺失值。日志窗口的说明如下:NOTE:Missing values were generated as a result of performing an operation onmissing values.3.2 使用 SAS 函数SAS 有 400 多个函数,主要涵盖如下领域:函数基本形式:function-name(argument,argument,),所有的函数都需要
3、括号,即使没有参数。下面的程序计算使用 MDY 函数,MDY 函数需要三个参数:月、日、年。Birthday=MDY(MonthBorn,DayBorn,YearBorn);函数可以嵌套,即一个函数可以是另一个函数的参数。比如:NewValue=INT(LOG(10);例子 有一个南瓜雕刻比赛的数据,pumpkin.dat 数据包含了参赛者的名字、年龄、雕刻的南瓜类型、报名日期、五位裁判给出的分数。下面的代码读取了数据、创建了两个新变量、转换了一个大小写:AvgScore 使用均值函数创建的变量,计算参数的均值,这与直接相加再除以 5 不同的地方在于,当参数中出现缺失值时,直接相加再除的方法返
4、回缺失值,而均值函数计算非缺失参数的均值。DayEntered 变量使用 DAY 函数,返回日期在一个月里的天数。Type 用大写转换函数将原来的字母转换成大写字母。结果是:3.3 选择 SAS 函数3.4 使用 IF-THEN 语句条件语句 IF-THEN 的基本形式为:IF 条件 THEN 执行;比如:IF Model=Mustang THEN Make=Ford;条件语句中的一些基本比较符号:还有 IN 比较符,比如这句中 IF Model IN(Corvette,Camaro) THEN Make=Chevrolet;代表当Model 为 Corvette 或 Camaro 的时候,将
5、 Chevrolet 赋给 Make。一个条件只能有一个执行,如果要多个执行,则需要 DO 和 END 关键字。可以用 AND 和 OR 来定义多个条件:IF Model=Mustang AND Year1975 THEN Status=classic;例子 如下的数据包含了模型的名字、年份、制造商和颜色:下面的代码从 cars.dat 的原始文件中读取数据,使用 IF-THEN 语句填满缺失值,并创建一个新变量 Status输出结果如下:3.5 用 IF-THEN 语句将观测值分组IF THEN/ELSE 的一般形式为:IF condition THEN action;ELSE IF con
6、dition THEN action;ELSE IF condition THEN action;用 else 语句与直接用多个 IF-THEN 语句比起来,有两个优势,第一是更有效率,电脑将占用更少的时间;第二是 else 可以确保你的两个 condition 之间互斥。有时候最后一个 ELSE 只有 action,没有 IF-THEN:例子 有一个住房改善的数据,home.dat,包括了姓名、改善工作、改善成本:下面的代码读取数据,并新建了一个 CostGroup 的变量。根据 Cost 的值将数据分成high、medium、low 和 missing 三类:输出结果是:3.6 构造子集I
7、F 语句可以构造子集,取数据集中的部分数据。基本形式为: IF expression; 比如: IF Sex=f;如果 IF 条件中的数据是真,则数据步将继续执行。还可以使用 DELETE 语句,来删除哪些不要的数据: IF expression THEN DELETE;这两句话是等价的: IF Sex=f; IF Sex=mTHEN DELETE;例子 有关于莎士比亚歌剧的清单,Shakespeare.dat,包含歌剧名、首次表演年份、类型:下面的代码读取数据,并且用 IF 语句构造一个只包含喜剧(comedies)的子集:输出结果如下:观察日志有时能很好的保证我们截取了我们要的数据:在这个
8、例子中,用 DELETE 等价的语句为:IF Type=tragedy OR Type=romance OR Type=history THEN DELETE;3.7 处理 SAS 的日期数据日期数据的处理很棘手,有的月份有 31 天、有的 30 天、有的 28 天。SAS 简化的日期数据,将所有的日期转化成一个以 1960 年 1 月 1 日为起点的数。比如:SAS 处理日期数据的三个工具为:读取数据的 informats,使用数据的函数( functions) ,打印数据的 formatsInformats 读取日期数据需要用 formatted input。比如,如何告诉 SAS 用 M
9、MDDYY10. imforat 读取名为 BirthDate 的变量:INPUT BirthDate MMDDYY10.;设定默认的百年 07/04/76 这样的数据可能是 1976,也可能是 2076、1776。因此需要YEARCUTOFF=来指定一个一百年的第一年,默认的是 1920 年。下面的语句就是告诉 SAS 将一个两位年份的日期解释为 1960 年到 2049 年之间:OPTIONS YEARCUTOFF=1950;SAS 表达式中的日期 一旦被以 SAS 日期格式读取之后,可以将此数据想其他数值数据一样用在表达式中。比如像为图书馆的书设定 21 天的还书日期,只需要在结束日期上
10、加上21:OPTIONS YEARCUTOFF=1950;通过在表达式中加入引号和字母 D,可以将一个日期当做常数来使用,如下的代码创建了一个 EarthDay05 的变量,并且等于 April 22,2005EarthDay05=22APR2005D;函数 SAS 日期函数使得操作大大简便,比图 today()返回今天的日期。语句 DaysOverDue=TODAY()-DateDue;可以计算一本书应归还还剩余的期限。Fomats 打印日期数据时,还需要将数值换成日期,下面的 FORMAT 语句告诉 SAS 用WEEKDATE17.格式打印变量 BirthDate。FORMAT Birth
11、Date WEEKDATE17.;例子 图书馆有借书卡数据,Dates.dat,包含持卡人姓名、出生日期、卡办理日期。下面的代码读取数据,计算变量使用期限(expiredate) ,使用期限为 3 年;变量expirequarter 计算使用期限的四分之一,使用函数 QTR() 。接着用 IF 语句来判断一个卡是否为新卡,在 2003 年 1 月 1 日之后办理的,为新卡:输出结果为:注意 BirthDate 没有用日期格式。3.8 可选择的 Date Informats,Functions 和 Formats下面是例子:3.9 使用 retain 和 sum 语句当开始数据步的每一个观测值迭
12、代时,SAS 会先将所有变量值设为确实,再通过 input 和分配语句改变。Ratain 和 sum 语句可以改变这种方式,Retain 语句 retain 语句可以让 SAS 保存前一次变量的值。它可以出现在数据步的任何位置,基本形式为: RETAIN variable-list;也可以指定一个初始值,而不是用缺失值或前一次的值代替初始值RETAIN variable-list initial-value;Sum 语句 SUM 语句用于你想将一个表达式的值累加到一个变量上去时,基本形式为:variable+expression;这个语句将表达式的值赋给变量,同时将变量的值保留到下一次迭代。这
13、个变量必须是数值型,且初始值为 0。因此,语句等价于如下形式:RETAIN variable 0;variable=SUM(variable,expression);例子 有一个关于本赛季棒球比赛的数据,games.dat,包含比赛日期、参赛队伍、hit 数据、runs 数据现在需要增加两个变量,一个反应本赛季的总 runs 数,一个反应一场比赛中最大的 runs数。下面的代码用 sum 语句实现总 run 数,用 retain 和 max 函数实现最大 runs 数:变量 maxruns 取前面迭代的 maxruns 和 runs 中最大值;变量 runstodate 将每一场比赛的runs
14、 都加到自己身上。结果如下:3.10 用数组简化程序对于太多变量要处理的程序,数组将大大简化程序。SAS 中,数组是一组变量,变量可以是已存在的,也可以是新创建的。数组在数据步中用 ARRAY 来定义,基本形式为:ARRAY name(n) $ variable-list;Name 是数组名,n 是变量数,()也可以用和代替。如果变量是字符串,则需要$ ,且变量是新创建的字符串时,$是必须的。变量名依照顺序排列,如数组:ARRAY store(4) Macys Penneys Sears Target;则 store(1)是 Macys,store(2)是 Penneys,store(3) 是
15、 Sear,store(4) 是 Target。数组本身不储存在数据集中,只有在数据步中才被定义。命名规则与变量一样(不超过 32字节,以字母、下划线开头,只能包含字母、数字、下划线)例子 广播电台 wbrk 做了一份关于歌曲的听众调查,对 10 首歌进行打分,分值在 1-5,如果没听过则填 9。数据文件 wbrk.dat 包括了被访者姓名、年龄、以及十首歌的打分。下面的代码将所有打分为 9 的改为缺失值:十首歌被放入 song 的数组中。输出结果如下:注意这里数组没有被保存到数据集中,而 i 被保存了。3.11 列出变量名的快捷方式如果想把 100 个变量放入数组,并不需要一个一个变量名的输
16、入,有快捷方式可以列出变量名。Number range lists 开始于同一个单词,结尾于连续的数字的,可以使用 Number range list。比如:Name range lists 这种列表是依据变量在数据集中的排列顺序来的,比如,创建如下数据步:则变量的排列顺序就为:Y A C H R那么可以依照这个顺序用“put 第一个变量-最后一个变量”来简化:如果不能确定数据集中变量的顺序,可以用 proc contents 的 postion 选项来查看。下面的代码列出了永久数据集 distance 的变量顺序:Special sas name list 例子 广播电台 WBRK 想要修改前面的代码(将 9 改为缺失值) ,使用 mean 函数计算平均分数:程序中,当原始变量(domk-ttr)值为 9 时,song 变量值为缺失值,否则就把原始变量的值赋给 song 变量。另外 avgscore 计算平均值: