从程序员到数据科学家:SAS 编程基础 (08)- 表达式
2017-04-26 01:00
507 查看
l 算术运算符:用于数值常量或变量进行算术运算,包括加法 +、 减法 -、 乘法 *、 除法 / 和乘方 ** 。 运算符的优先顺序为:乘方优先,先乘除后加减。
运算符 | + | - | * | / | ** |
释 义 | 加 | 减 | 乘 | 除 | 乘方 |
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 |
释 义 | 取最小值 | | 字符串通配符:%任意字符,- 单个字符 |
<> .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;
系统输出:
结语:表达式是构成语句的基础,而语句则是构成程序的基础。就像我们说话的时候会分成段落、句子一样,表达式是我们完整句子里的每一个片段。良好的表达式应该是具有非常清晰的变量/常量命名,而且表达式中的运算关系非常明确,没有歧义易于维护的语句片段!
相关文章推荐
- 从程序员到数据科学家:SAS 编程基础 (01)
- 从程序员到数据科学家:SAS 编程基础 (06)- DATA步与PDV
- 从程序员到数据科学家:SAS 编程基础 (02)
- 从程序员到数据科学家:SAS 编程基础 (04)
- 从程序员到数据科学家:SAS 编程基础 (03)
- 从程序员到数据科学家:SAS 编程基础 (05)
- 从程序员到数据科学家:SAS 编程基础 (07)- 常量与变量
- 黑马程序员_java基础笔记(08)...GUI,网络编程,正则表达式
- 我与python约个会:08.程序编程基础2~基本数据类型
- 黑马程序员_java基础笔记(08)...GUI,网络编程,正则表达式
- 黑马程序员_java基础笔记(08)...GUI,网络编程,正则表达式
- 程序员的7种武器 -〉正则表达式、编程语言、数据库、算法、软件调试、开发环境、编程
- 第9讲AE编程基础_数据加载与数据显示
- OpenGL基础图形编程 - OpenGL数据类型和函数名
- DirectShow基础编程 采集视频数据
- 数据类型,运算符和表达式02 - 零基础入门学习C语言03
- Java中将数据由UTF8转换成GB2312格式-Java基础-Java-编程开发
- 用游戏串起程序员的基本功-Java基础-Java-编程开发
- 数据类型,运算符和表达式01 - 零基础入门学习C语言02
- java中删除数据库中重复数据的几个方法-Java基础-Java-编程开发