您的位置:首页 > 职场人生

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

2017-04-26 01:00 507 查看


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

变  体

 

~=

 

 

=>

=<

 

其中运算符 EQ、NE、GT、LT、GE、LE为对应运算符的别名,数值型基于数值大小比较,而字符型基于从前到后字符的码点值大小进行比较;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

注意:与传统的C或C++ 的等于/不等于运算符(== 和 !=)不同,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

注意:与传统的C或C++ 的逻辑运算符与(&&)、或(||)、非(!)不同,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;

缺省地,累加赋值语句初始值为 0 开始,我们可指定其初始值,比如下面的代码会输出 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;

系统输出:

    



结语:表达式是构成语句的基础,而语句则是构成程序的基础。就像我们说话的时候会分成段落、句子一样,表达式是我们完整句子里的每一个片段。良好的表达式应该是具有非常清晰的变量/常量命名,而且表达式中的运算关系非常明确,没有歧义易于维护的语句片段!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  编程