从程序员到数据科学家:SAS 编程基础 (08)- 表达式


SAS 表达式(SAS Expression)是SAS 语句的组成部分,是构成SAS程序指令集合的一系列操作数和运算符的集合。操作数包括常量和变量,运算符则包括算术运算关系运算逻辑运算等运算类型。SAS表达式也包括赋值运算以及一些SAS特有的运算类型。SAS 默认不支持位运算,但可以利用变通的方法实现。

l  算术运算符:用于数值常量或变量进行算术运算,包括加法 + 减法 - 乘法 * 除法 和乘方 **  运算符的优先顺序为:乘方优先,先乘除后加减。

运算符

+

-

*

/

**

  

乘方

data _null_

    a= 3; b=4; c=5; d=6;

    d = a + b;

    e = a * b;

    f = a / b;

    g = a ** 2;  

    h = a + b  * c  / 6;

    i =(a + b) * c  / 6;

    put "d=" d "e=" e "f=" f "g=" g "h=" h "i=" i;

run;

  输出结果为:d=7 e=12 f=0.75 g=9 h=6.3333333333 i=5.8333333333

l  关系运算符:用于比较常量或变量(数值型或字符型)的大小。关系运算符包括:

运算符

=

^=

>=

<=

  

等于

不等于

大于

小于

大等于

小等于

  

EQ

NE

GT

LT

GE

LE

  

 

~=

 

 

=>

=<

 

其中运算符 EQNEGTLTGELE为对应运算符的别名,数值型基于数值大小比较,而字符型基于从前到后字符的码点值大小进行比较;SAS中缺失值和空格字符在比较运算中比任何可打印字符都小。为了和早期版本兼容,SAS不等于运算符 ^= 也可以写作 ~= ,而小等于<= 和大等于 >= 也可以写作 =<  =>。比如:

data _null_

    a= 3; b=4; c=5; d=6;

    e=(a ^= b); f=(a ~=b );

    put "(a^=b)=" e "(a~=b)=" f;

    g=(a => b); h=(a =< b );

    put "(a=>b)=" g "(a=<b)=" h;

run;

输出结果为:

(a^=b)=1 (a~=b)=1

(a=>b)=0 (a=<b)=1

注意:与传统的CC++ 的等于/不等于运算符(==  !=)不同,SAS采用单字符 =  ^=来表示SAS也为一些列的操作符提供了别名功能。

SAS语言还有自己特殊的关系表达式写法比如SAS可以把变量写在中间,变量前后都是运算符和操作数。比如: op1 <= var1 <= op3其对应的别名写法就是 var1 BETWEEN op1AND op3,表示 var1介于op1  op3 之间。

l  逻辑运算符:用于表达式中的逻辑(布尔)运算,包括

运算符

&

|

^

  

AND

OR

NOT

  

  

 

¦  !

~

 

在计算机术语中,FALSE表示0,而TRUE 表示1。在SAS 程序中,0  缺失值 视为 FASLE,而将任何 非0  非缺失值 视为真。因此SAS 程序中单个数值变量也是可以参与逻辑运算的。   

data _null_

    a= 3; b=4; c=5; d=6;

    e =(a<b)|(c>d);

    e2=(a<b)¦(c>d);  e3=(a<b)!(c>d);

    f= (a<b) & (c>d);

    g=^(a<b);

    put "or=" e "and=" f "not=" g;

    put "or=" e2 "or=" e3;

run;

输出结果为:

or=1 and=0 not=0

or=1 or=1

注意:与传统的CC++ 的逻辑运算符与(&&)、或(||)、非(!)不同,SAS采用单字符& | ^ 来表示;SAS || 表示字符串拼接操作。

l  特殊运算符:除了上面的运算符,SAS 语言还有一些其他语言没有的特殊运算符,主要包括:

运算符

<> 

IN

||

  

取最大值

属于

字符串拼接

运算符

>< 

 

LIKE

  

取最小值

 

字符串通配符:%任意字符,单个字符


取最大值/最小值预算符<>  ><):相当于 MAX/MIN函数,但在SAS中被作为一种运算符存在。如果缺失值是比较运算的一部分,SAS会用缺失值的排序顺序进行比较,比如 .A <> .Z 返回 .Z

集合运算符IN SAS语言特有的运算符用于检查变量的值是否在一个给定的列表中。列表内必须为常量、缺失值或枚举器 Iterator。比如 Name IN (“Alfred”, “Alice”)。

data _null_

    a= 3; b=4; c=5; d=6;

    c=(a<b); d=(a=b); e= a IN (3 , 4, 5 );

    put "(a<b)=" c "(a=b)=" d "e=" e;

run;

输出结果为: (a<b)=1 (a=b)=0 e=1

字符拼接运算符 || 用于连接两个字符型变量或常量,它并不删除前一个字符串的尾部的空格,因此我们需要使用 TRIM函数删除尾部空格来达到预期效果比如TRIM(var1) || var2  

data _null_

    max= 3<>5;

    min= 3><5;

    ab= 'a'||'b';

    put "Max=" max "Min=" min "'a'||'b'=" ab;

     length var1 $8 var2 $8;

     var1='hello'; var2='kitty';

     var3=var1 || var2;

     put "var3=" var3;

     var4=TRIM(var1) || var2;

     put "var4=" var4;

run;

输出结果为:

Max=5 Min=3 'a'||'b'=ab

var3=hello   kitty

var4=hellokitty

字符串通配符比较 LIKE 用来在一些表达式中模糊匹配字符串比如WHERE 语句中的 LIKE 字符串比较。其中百分号 % 表示任意字符,下划线 _ 表示单个字符。

data myclass;

    set sashelp.class;

    where Name like "%%";

run;

proc print;

run;

输出如下:

data myclass;

    set sashelp.class;

    where Name like "_";

run;

proc print;

run;

  输出如下:

注意:在WHERE 语句中运算符 IS MISSING  IS NULL分别用来判断变量是否为缺失值或空值,等价于 var=.  var=’’ 关系运算符。

l  运算符优先顺序

当一个表达式包含多个运算符,且没有使用括号来显式分割子表达式时,就会涉及到运算符优先顺序问题,总体上:

首先,与其他计算机语言一样,表达式中的括号 () 具有最高优先级,用户也可以使用括号来人为分隔表达式指定结合顺序,避免潜在的歧义性。

其次,乘方运算 ** 和取正负号的单目运算符   为第二优先级;然后才是算术运算,关系运算和逻辑运算。

另外,取最大/小值操作符 <>  ><仅次于乘方运算 **,但优先于取正负号运算。字符运算符|| 和集合运算符 IN优先于关系运算符,但比算术运算符优先级低。

下表为SAS运算符优先顺序表:

优先级

运算符

类别

释义

1

()

 

括号中的表达式最先求值

2

**

 

方运算

 

<>  ><

SAS特定

取最大值、最小值运算

3

+ -

单目运算

取正/负号

4

* /

算术运算

乘除法

5

+ -

算术运算

加减法

 

||

SAS特定

字符串拼接

 

IN

SAS特定

集合包含运算

6

=  <>  >  <

>=  <=

关系运算

比较运算符:等于、不等于,大于,小于,大等于,小等于

7

^  &  |

逻辑运算

优先级为 NOT AND OR, 从左到右结合

8

=

 

赋值运算符

 

SAS表达式中乘方、取正负号运算符、逻辑非、取最大/小值6种运算符(红色)为第一优先级且从右到左进行求值,其他的运算符都是从左到右进行求值。实践中鼓励大家明确使用括号来分隔表达式,或者将一个复杂表达式分解为多个赋值语句来提高代码的可读性!

l  SAS赋值语句

赋值语句用来对一个表达式进行求值,然后把结果赋给一个变量(新的或者已有的)。 赋值语句是极少数不需要以关键字开始的SAS 语句

var1 = Expression;

等号前后分别为变量名和表达式。右侧表达式在求值时,需要根据前面的运算符优先顺序进行求值如果右侧表达式中包含缺失值,则计算的结果为一个缺失值

当表达式右侧包含左侧变量时,变量首先会在求值过程中被使用,最后将结果存储在左侧的变量中。考察如下代码:

data _null_;

    a=a+1;

    b=3; b=b+1;

    put a= b=;

run;

系统不会输出a=1,而是输出a等于缺失值:a=.,原因是a在右侧被使用的时候为缺失值,而表达式中包含缺失值则计算结果为缺失值。对于程序b则会输出 b=4.

l  SAS累加赋值语句

SAS 步中还有一个很特殊的变量累加赋值语句,它没有关键字也不需要等号,它是极少数不需要关键字开始的SAS语句之一。其形式为:var+Expression

其中 var 被隐含为数值型变量,SAS会将它初始化为0,然后在DATA步循环中不断将表达式求值,然后赋给该变量。另外,该变量在DATA步循环中也不会被清零,就像有 RETAIN语句作用于该变量一样。考察如下代码:

data _null_;

    set sashelp.class;

    c+1; /*奇葩代码有木有但得承认它很简洁*/

    put c=;

run;

系统输出 c=1 c=2 … c=19。该语句等价于 retain c 0 c=sum(c,1); 语句。

data _null_;

    set sashelp.class;

    retain c 0; c=sum(c,1); /*介个代码才比较像人话*/

    put c=;

run;

缺省地,累加赋值语句初始值为 开始,我们可指定其初始值,比如下面的代码会输出 c=101 c=102 … c=119

data _null_;

    set sashelp.class;

    retain c 100; /*指定初始值*/

    c+1;

    put c=;

run;

l  RETAIN 语句

RETAIN语句可以让 INPUT 语句或赋值语句创建的变量DATA步隐性循环中得以保持,避免被用缺失值重新初始化。它是申明性语句,并非执行性语句。其基本形式为:

retain var1 … varN value1 … valueN;

其中变量列表可以是系统预定义的列表 _ALL__NUMERIC_或者 _CHAR_,分别表示全部变量,全部数值型变量或字符型变量。另外,如果一个变量仅仅出现在 RETAIN 语句中却从未被赋值,该变量是不会被输出到输出数据集的。

注意:RETAIN 语句用来指定在DATA步循环中不要重新初始化为缺失值的那些变量;而KEEP语句用来指定需要输出到目标数据集中的那些变量,与之相对应的语句是 DROP语句。

比如下面的代码,我们可以对 sashelp.class 的所有年龄求和,考察如下代码你会发现 total 能得到正确值,而total2 只有第一个观测有值,其他都是缺失值。

data _null_;

    set myclass;

    retain total 0/*初始化为 0*/

    total=total+ Age;

    if _N_=1 then total2=0;/*初始化为 0*/

    total2=total2+Age;

    put age= total= total2=;

run;

系统输出:

Age=14 total=14 total2=14

Age=13 total=27 total2=.

Age=13 total=40 total2=.

Age=16 total=56 total2=.

Age=14 total=70 total2=.

Age=12 total=82 total2=.

Age=13 total=95 total2=.

Age=14 total=109 total2=.

Age=12 total=121 total2=.

Age=15 total=136 total2=.

Age=12 total=148 total2=.

Age=15 total=163 total2=.

Age=11 total=174 total2=.

Age=11 total=185 total2=.

Age=15 total=200 total2=.

Age=15 total=215 total2=.

Age=12 total=227 total2=.

Age=12 total=239 total2=.

Age=14 total=253 total2=.

DATA 步中,有些变量默认具有保持特性,它们不需要额外的 RETAIN 语句进行指定。当然,除了 _N_  _ERROR_ 外,我们可以为任何变量使用 RETAIN语句来指定初始值。默认具有RETAIN保持特性的变量如下:

1)         自动变量 _N_, _ERROR_ 以及 _I_, _CMD_  _MSG_

2)         SAS语句 SET, MERGE, MODIFY  UPDATE 语句中读入的变量,或这些语句中使用END=  IN= 选项创建的变量

3)         SAS语句 FILE, INFILE语句中使用 BY= 选项创建的变量

4)         累加求和变量

5)         临时数组中指定的数据元素

6)         SAS语句ARRAY 中初始化的数组元素、或者这些数组元素的数组元素。

当我们需要对数据集中的观测进行遍历时,我们经常会用到 retain 语句。灵活应用它配合隐性循环可以完成一些复杂的功能。比如下面的例子查找 sashelp.class 中男生和女生中的最矮身高。

proc sort data=sashelp.class out=temp;

   by sex;

run;

data myclass;  

   set temp;

   retain Shortest;

   by sex;

   if first.sex then Shortest=height;     

   Shortest=Shortest><height;

   if last.sex then output;

    keep sex Shortest;  

run;

proc print data= myclass; run;

系统输出:

    

结语:表达式是构成语句的基础,而语句则是构成程序的基础。就像我们说话的时候会分成段落、句子一样,表达式是我们完整句子里的每一个片段。良好的表达式应该是具有非常清晰的变量/常量命名,而且表达式中的运算关系非常明确,没有歧义易于维护的语句片段!

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值