本文重点:

  • 使用RETIAN,INPUT在每次循环执行时保留上一次PDV中的变量值。
  • SUM语句和SET语句会自动RETAIN变量。

1. RETAIN语句

1.1 Example 1

先来看看在DATA步不使用和使用RETAIN语句的差异

没有使用RETAIN:

DATA WITHOUT_1;
PUT "Before the INPUT statement: " _ALL_;
INPUT X @@;
PUT "After the INPUT statement: " _ALL_ /;
DATALINES;
1 2 . 3
;

使用RETAIN:

DATA WITH_1;
RETAIN X;
PUT "Before the INPUT statement: " _ALL_;
INPUT X @@;
PUT "After the INPUT statement: " _ALL_ /;
DATALINES;
1 2 . 3
;

注意比较两段代码的输出红色矩形的内容,结合上一篇博客里讲的PDV,不难发现:

  • 不使用RETAIN,INPUT在每次循环执行时会把PDV中的变量值清空,即置为(.)。
  • 使用RETIAN,INPUT在每次循环执行时保留上一次PDV中的变量值。

实际上,上面这个例子里数据集WITHOUT_1和WITH_1的内容是一样的,下面来看一个必须要用RETAIN的例子。

1.2 Example 2

考虑这样一种场景:我们的数据集中有缺失值,我们想用该缺失值的前一个非缺失值来填补该缺失值,比如我们的数据是1,2,.,3填补后是1,2,2,3。
这在SAS中很好处理,我们只需要用一个变量记住上一个非缺失值即可:

DATA WITHOUT_2;
PUT "Before INPUT: " _ALL_ ;
INPUT X @@;
IF X NE . THEN OLD_X = X;
ELSE X = OLD_X;
PUT "After assignment: " _ALL_ /;
DATALINES;
1 2 . 3
;

遗憾的是这段代码并没有实现我们的目的

查看日志,问题就很明显了,因为没有使用RETAIN,所以在数据步的每一次循环开始时,PDV中的变量均被置空,所以OLD_X每一次都是空:

既然想让OLD_X记住DATA步每次迭代的前一个值,我们RETAIN住OLD_X即可:

DATA WITH_2;
RETAIN OLD_X;
PUT "Before INPUT: " _ALL_ ;
INPUT X @@;
IF X NE . THEN OLD_X = X;
ELSE X = OLD_X;
PUT "After assignment: " _ALL_ /;
DATALINES;
1 2 . 3
;

1.3 Example 3

考虑这样一种场景:在我们读入数据的时候,我们想给每个数据加一个顺序的行号,第一条观测是1,第二条观测是2,依次到最后一条观测。

下面用RETAIN语句实现:

DATA WITH_3;
RETAIN SUBJECT 0;
PUT "Before the INPUT statement: " _ALL_ ;
INPUT X @@;
SUBJECT = SUBJECT + 1;
PUT "After the INPUT statement: " _ALL_ /;
DATALINES;
1 3 5
;

RETAIN SUBJECT 0;表示在DATA步的每一次迭代时RETAIN住SUBJECT这个变量,不要将其置为空,“0”表示SUBJECT的初始值。

上面这段代码,可以利用SAS中的SUM语句进行简化:

DATA WITHOUT_4;
PUT "Before the INPUT statement: " _ALL_ ;
INPUT X @@;
SUBJECT

+ 1;

 /* SUM statement */
PUT "After the INPUT statement: " _ALL_ /;
DATALINES;
1 3 5
;

注意到SUM语句的作用:

  1. 不需要显示地用“=”赋值
  2. 不需要显示地初始化SUBJECT,它会自动初始化为0
  3. 不需要显示地RETAIN,它会自动RETAIN变量

其实,如果你还记得上一篇博客中我们在讲PDV时提到的自动变量_n_,这段代码可以更简洁:

DATA USE_n_;
PUT "Before the INPUT statement: " _ALL_ ;
INPUT X @@;
n

=

_n_;
PUT "After the INPUT statement: " _ALL_ /;
DATALINES;
1 3 5
;

1.4 Example4

上一个例子中我们发现SUM语句会自动RETAIN变量,其实SAS中的SET语句也会自动RETAIN变量:

DATA ONE;
INPUT X Y;
DATALINES;
1 2
;
DATA TWO;
IF _N_ = 1 THEN SET ONE;
PUT "Before INPUT statement: " _ALL_;
INPUT NEW;
PUT "After INPUT statement: " _ALL_ / ;
DATALINES;
3
4
5
;

看一下日志,就发现SET的确自动RETAIN了变量X,Y。最开始,_N_=1,将X=1,Y=2读入,然后_N_=2,_N_=3等后面的每一步,粉色框里的X,Y值并没有在DATA步的每次迭代中被置空。

参考资料:《Longitudinal Data and SAS: A Programmer's Guide》

SAS笔记(2) RETAIN语句的更多相关文章

  1. SAS笔记

    SAS基础知识 SAS里面的PROC一览 The ACECLUS Procedure : 聚类的协方差矩阵近似估计(approximate covariance estimation for clus ...

  2. SAS笔记(3) LAG和DIFF函数

    在实际的应用中,我们会想查看当前观测的上一个观测值,在上一篇博客中我们使用了RETAIN语句来记录上一条观测,其实SAS还提供了一个很好用的函数LAG.当我们使用函数时,一定要明确该函数的返回值是什么 ...

  3. 【SQL Server学习笔记】Delete 语句、Output 子句、Merge语句

    原文:[SQL Server学习笔记]Delete 语句.Output 子句.Merge语句 DELETE语句 --建表 select * into distribution from sys.obj ...

  4. SAS学习笔记4 基本运算语句(lag、retain、_n_函数)

    lag:返回的是上一次lag函数运行时的实参,即lag(argument)=上一次lag函数执行时的argument retain:对变量进行值的初始化和保留到下一个迭代步 _n_:data步的自动变 ...

  5. SAS学习笔记43 宏语句

    流程控制 %GOTO语句与%label语句是结合起来使用的.首先通过%label语句定义一个位置,使用%GOTO语句可直接将程序的执行位置跳到该label标记位置,达到控制程序执行顺序的目的.可实现与 ...

  6. SAS学习笔记7 合并语句(set、merge函数)

    set函数:纵向合并数据集 set语句进行纵向合并.set语句的作用是将若干个数据集依次纵向连接,并存放到data语句建立的数据集中.若set后面只有一个数据集,此时相当于复制的作用 注:data语句 ...

  7. SAS学习笔记35 options语句

  8. SAS学习笔记32 select语句

  9. SAS学习笔记8 循环语句(do函数)

    do-end函数

随机推荐

  1. NULL 与空字符串

    空字符串 '' 不占内存空间; NULL占一个字节的空间; 空字符串 的判断用 == <> NULL值用 is null ifnull();

  2. unit Base64Unit;

    unit Base64Unit; unit Base64Unit; //Download by http://www.codefans.net interface uses Classes, SysU ...

  3. 理解VMware虚拟网络

    简述:VMware虚拟网络概述.实现虚拟网络上网 Part0 子网掩码.DHCP.NAT,这些点请自行百度,百度百科讲的很清晰. Part1 转载:本文出自 "王春海的博客" 博客 ...

  4. LXC linux容器简介——在操作系统层次上为进程提供的虚拟的执行环境,限制其使用的CPU和mem等资源,底层是linux内核资源管理的cgroups子系统

    1.LXC是什么? LXC是Linux containers的简称,是一种基于容器的操作系统层级的虚拟化技术. 2.LXC可以做什么? LXC可以在操作系统层次上为进程提供的虚拟的执行环境,一个虚拟的 ...

  5. JavaWEB - 静态include指令、动态Include指令

    (一)使用静态include指令 <%@ page language="java" contentType="text/html; charset=gb2312&q ...

  6. HEOI2017题解

    Day 1 : T1 : 期末考试 很水的一道题,但是自己搞了大半天过不了大样例. 最后还A了... 主要思想就是枚举最后一个完成的任务的时间 然后对两部分的代价分类讨论统计一下. (考试代码,略丑) ...

  7. 浅谈vue路由原理

    Vue的路由实现:hash模式 和 history模式 hash模式:在浏览器中符号“#”,#以及#后面的字符称之为hash,用window.location.hash读取: 特点:hash虽然在UR ...

  8. SLF4j+LOG4j

    工作笔记:在myeclipse 中创建一个java project 创建一个 TestSlf4J 类 import org.slf4j.Logger; import org.slf4j.LoggerF ...

  9. BZOJ1636&&1699:[USACO2007JAN]Balanced Lineup

    浅谈\(RMQ\):https://www.cnblogs.com/AKMer/p/10128219.html 题目传送门:https://lydsy.com/JudgeOnline/problem. ...

  10. debian上安装codeblocks

    1.查看linux的版本uname -a 2.在官网上下载稳定版的codeblocks(www.codeblocks.org) 3.解压codeblocks后,进入到文件夹中用root身份执行dpkg ...