• SAS笔记(2) RETAIN语句


    本文重点:

    • 使用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
    ;

    a1

    使用RETAIN:

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

    a2

    注意比较两段代码的输出红色矩形的内容,结合上一篇博客里讲的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
    ;

    遗憾的是这段代码并没有实现我们的目的
    a3
    查看日志,问题就很明显了,因为没有使用RETAIN,所以在数据步的每一次循环开始时,PDV中的变量均被置空,所以OLD_X每一次都是空:

    a4

    既然想让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
    ;

    a5

    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
    ;

    a6

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

    a7

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

  • 相关阅读:
    九省联考2018 IIIDX
    WC2020 猜数游戏
    Gym101821D Search Engine
    Gym102586B Evacuation
    Gym102576D Clique
    UOJ498 新年的追逐战
    LOJ6703 小 Q 的序列
    Codechef A Leisurely Journey
    LG5050 多项式多点求值 和 LG5158 多项式快速插值
    PE427 n-sequences 和 ZJOI2020 抽卡
  • 原文地址:https://www.cnblogs.com/zhangzhangwhu/p/7223163.html
Copyright © 2020-2023  润新知