添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

1 创建和重定义变量

创建和重定义变量,是SAS中最受人欢迎的功能之一,你可以用以下基本形式的赋值语句,来创建和重定义变量:

variable = expression ;

variable 是变量名,可以是新变量或已有变量。expression 可以是常量、另一个变量 或 数学表达式。以下是基本类型赋值语句的示例:

表达式类型

3.1 使用if-then语句(单分支)

if-then语句,又称为条件逻辑,用法类似于python中分支结构里的单分支(只有一个真区间)。

语法:if condition then action ;

在条件condition为真时,执行then后面的action语句。condition可以是常量、变量或表达式,通过比较运算符、in运算符等进行比较。
比较运算符

DO 组合

一个IF-THEN语句只能由一个动作,如果想要执行多个动作,则可以添加关键字DO和END。

do语句将在其后出现直至与之匹配的end语句为止的所有SAS语句视为一个单元。do语句、end语句和它们之间的所有语句一起,被称为do组合。

if condition then do;
	action1;
	action2;
逻辑运算符

IF-THEN语句中condition条件判断,还能包含逻辑运算符ADN、OR及其组合,来进行多个条件的组合判断。

  • PROC FORMAT 生成的用户自定义格式的PUT函数
  • 而创建分组变量的最简单和最常见方法,就是使用一系列IF-THEN语句。并且,通过在IF语句中添加关键字ELSE,可以告知这些语句是相关的,用法类似于Python中的双分支和多分支。
    IF-THEN/ELSE 语句

    基本语法:

    if condition then action;
    	else if condition then action;
    	else if condition then action;
    

    注意,ELSE语句是添加在IF-THEN语句前面,这样的语句可以是无限多个。ELSE语句保证分组的逻辑是相互排斥的,一旦观测满足某个条件,SAS就会跳过不执行该系列其余语句。

    有时,ELSE语句系列中的最后一个ELSE会不同,它只包含一个动作而没有TF或THEN。这种ELSE充当默认值的角色,它将执行所有未能满足任何先前的IF语句的观测。但你只能有一个这样的语句,它必须是 IF-THEN/ELSE 系列中最后一个语句。

    语法如下:

    if condition then action;
    	else if condition then action;
    	else if condition then action;
    	else antion
    
    if cost = . then costgroup = 'missing';
    	else if cost < 2000 then costgroup = 'low';
    	else if cost < 10000 then costgroup = 'medium';
    	else costgroup = 'high';
    

    4 提取数据中的子集(if语句/delete语句)

    在SAS中,提取数据集中的某些观测而排除其余观测,最常见的方法是 IF 语句和 WHERE 语句。IF语句的基本语法形式如下:

    if expression ;

    如:if sex = 'f' ;

    可以把 IF 语句看成是 IF-THEN语句的特例。其含义是:若表达式为真,则SAS继续执行data步;若表达式为假,则SAS停止处理该观测的后续语句,即该观测不会添加到正在创建的数据集,然后SAS接着处理下一个观测。

    简单地理解,可以把IF语句看成是一个开关:

  • if条件为真,开关打开,观测被处理
  • if条件为假,开关关闭,观测不被处理
    DELETE语句
  • 与IF语句告诉SAS要哪些观测相反,delete语句告诉SAS不要哪些观测。如果sex变量只包含两个变量且灭有缺失值,则下面两条语句等价。

    *if语句;
    if sex = 'f';
    *delete语句;
    if sex = 'm' then delete;
    

    总之,当更容易指定条件包含观测时,取子集用 IF 语句;而在更容易指定条件排除观测时,用 DELETE 语句。

    5 使用SAS日期

    SAS日期是等于 1960.1.1 以来的天数值。关于日期处理,SAS有专门的工具:日期输入函数、输出格式和操作日期的函数。

    可以使用格式化的输入方式,来读取日期型变量,把日期数据转换为 1960.1.1 以来的天数。

    示例:input birthday ANYDTDTE9. ; /* ANYDTDTEw是一种特殊的输入格式,能读取几乎任意格式的日期 */

    设置输入的默认世纪

    当遇到类似 07/04/76 的两位数年份日期数据时,SAS必须判断年份是在那个世纪,是1976,2076,还是其他?系统选项 YEARCUTOFF= 选项指定SAS使用的百年跨度的第一年,可以使用OPTIONS语句修改此值:

    示例:options yearcutoff = 1950 ;

    上面语句含义是告知SAS,将两位数的日期解释为发生在1950年开始,往后跨度100年,即1950年 ~ 2049年间。

    关于日期的更多输入格式,见page100。

    此外,一旦使用SAS日期输入格式来读取变量,它就可以像其他数值变量一样,在算术表达式中随意使用。如

    duedate = checkdate + 21 ; 也可以在SAS表达式中使用日期作为常量,如:day = '22apr2014'D ;

    5.1 常用SAS日期函数

    age = int(yrdif(birthdate, today(), 'age')) ;
    

    更多函数及其用法,参见page100。

    5.2 常用SAS日期输出格式

    如果打印SAS日期值,SAS将默认打印距离 1960.1.1 的实际天数,但这并不利于观察。所以,SAS提供了多种输出格式用来以不同的格式打印日期。

    示例:format birthdate worddate18. ;

    更多输出格式及其用法,参见 page100 和 page125。

    6 保留迭代初始值和累加(retain语句与求和语句)

    当SAS读取原始数据时,在DATA步每次迭代开始时会将所有变量设置为缺失值。这些值可以通过input语句或赋值语句来修改,但当SAS返回到data步的开始并处理下一个观测时,它们会被重新设置为缺失值。可以使用RETAIN语句和求和语句来改变这种方式。
    RETAIN语句

    ratain语句,能让变量的值从data步的一次迭代保留到下一个迭代。ratain语句能出现在data步的任何位置,常用的有两种语法形式:

    RETAIN  variable-list ;                  *variable-list指所要保留的变量;
    RETAIN  variable-list  initial-value ;   *initial-value是为变量指定初始值来代替缺失值进行迭代;
    

    求和语句不仅保留了上一次迭代的值,还将其值累加到表达式中,适用于将表达式的值累加到变量这种特殊场景。

    语法:variable + expression ;

    求和语句将表达式的值累加到变量中,同时将变量的 值从data步的一个迭代保留到下一个迭代。需要注意的是,该变量必须是数字,且初始值为0。可以使用RETAIN语句和SUM函数来重写此语句,两者等价。

    语法格式:

    RETAIN variable 0;
    variable = sum(varible, expression);
    

    综合示例如下:

    libname zdata "D:\data\sas_file";
    data zdata.gamestats;
    	infile "D:\data\sas_file\testdata.dat";
    	input month 1 day 3-4 team $ 6-25 hits 27-28 runs 30-31;
    	retain maxruns;
    	maxruns = max(maxruns, runs);
    	runstodata + runs;
    proc print data = zdata.gamestats;
    	title "games total";
    

    7 利用数组简化程序(array语句)

    数组是相似元素的有序集合

    若想对很对变量做同样的事情,你可以编写一系列赋值语句或者IF语句,但更简便的方法是使用数组。在SAS中,数组是一组变量,你可以将数组定义为喜欢的任何变量组,前提是它们全是数值 或 全是字符。SAS中使用data步中的ARRAY语句来定义。

    语法:array name (n) $ variable-list ;

    其中,name为数组名字,n是数组中的变量个数。在(n)的后面是变量名列表。列表中的变量个数必须等于括号中给出的数字(也可以使用 {} 或 [] 来代替括号),这被称为显式数组。如果变量是字符且之前未定义,则需要加 $ 符号。

    变量仅在data步运行时存在,不与数据集一起存储。可以给数组取任何名字,命名规则遵循SAS标准命名规则,但不能与数据集中的变量名相同。

    为使用方便,可以使用数组名称和下标,来引用变量,类似于python中的切片,不同的是下标是从1开始,且用的是括号(),如下:

    array store(4) macys penneys sears target ;

    则store(1)指代变量 macys , store(4)指代变量 target 。

    data zdata.songs;
    	infile "D:\data\sas_file\songs.dat";
    	input city $ 1-15 age wj kt tr filp ttr;
    	array song (5) age wj kt tr filp ttr;
    	do i = 1 to 5;                              /* DO循环类似于python中的for循环 */
    		if song(i) = 9 then song(i) = .;
    	end;										/* 结束循环 */
    

    8 使用变量名列表的快捷方式

    当编写的变量名称列表中变量数量过多时,推荐使用一种快捷方式 —— 变量缩写列表。
    函数中的缩写列表

    在函数中,缩写列表之前必须有关键字OF,如sum(of cat 8 - cat12)
    数字范围列表

    以相同字符开始,并以连续数字结尾的变量,可以时数字范围列表的一部分。只要数字时顺序相连的,就能以任何数字开始和结束。

    如果不确定内部顺序,可以使用proc contents中的 POSITION 选项来查找,作用是列出数据集中的变量,并按位置排序。

    libaname mydir "D:\data\sas_file";
    proc contents data = mydir.diatance position;
    名称前缀列表

    以相同字符开头的变量可以是名称前缀列表的一部分,可以在某些SAS语句和函数中使用。例如:

  • _NUMERIC_:表示数据集中所有数值变量
  • 这些名称列表在要计算某观测的所有数值变量的均值时(MEAN(OF _NUMERIC_)),或列出某观测所有变量的值时(PUT _ALL_)非常有用。

    data zdata.songs;
    	infile "D:\data\sas_file\songs.dat";
    	input city $ 1-15 age wj kt tr filp ttr;
    	array new (5) song1-song5;           /* 数字变量列表 */
    	array old (5) wj--ttr;               /* 名称范围列表 */
    	do i = 1 to 5;
    		if old(i) = 9 then new(i) = .;
            else new(i) = old(i);
        avgscore = mean(of song1-song5);     /* 缩写变量列表 */