楼主: vivienly121
751 1

[学习分享] SAS笔记:first 临时变量在 by 两个变量场景中的应用 [推广有奖]

  • 0关注
  • 0粉丝

大专生

31%

还不是VIP/贵宾

-

威望
0
论坛币
34 个
学术水平
0 点
热心指数
0 点
信用等级
0 点
经验
700 点
帖子
27
精华
0
在线时间
57 小时
注册时间
2012-12-21
最后登录
2018-7-17

vivienly121 学生认证  发表于 2018-1-11 18:20:14 |显示全部楼层
本帖最后由 vivienly121 于 2018-1-11 18:36 编辑

       总结一、通过first 临时变量结合by 两个变量,可以形成组中组的数据,然后对亚组挑选组中的第一个观测。                                      二、通过retain语句或累加语句对组中剩余的观测行进行标签的累加,可以实现给数据行打上组中第几条数据的标签。

       一、问题场景:一个患者(患者标识PID)会有多次就诊记录(就诊标识VID),每次就诊中可能会有多条手术记录,现在想给患者的每次就诊中的多次手术记录都打上标签(surgery_order):1、2...n 表明这是患者的第一次就诊时的手术、第二次就诊时的手术...第n次就诊时的手术。即长这样:

Obs PID VID surgery_order
11A1
21B2
31B2
41C3
52D1
62D1
72E2



      二、背景知识:         
          1、SAS可以实现“识别同一个组内的多个观测行数据中的第一个变量或最后一个变量”的功能,这个功能可以由“first 和 last ”临时变量实现。具体参考:http://blog.sina.com.cn/s/blog_760f92f701014s4s.html 、http://www.cnblogs.com/zhangzhangwhu/p/7230047.html

           2、retain语句:可以避免data步在每次迭代(每处理一行数据就是一次迭代)中将retain 的变量初始化为缺失。具体参考:http://www.cnblogs.com/zhangzhangwhu/p/7223163.html


          背景知识总结
                   1、first / last 变量只能在data步中使用。
                   2、first / last 变量使用时,需要在data步前
对标识这些观测为一个组的变量var(如一个患者的多条观测为一组,那么组标识变量就是患者的PID)进行排序:proc sort ...by var 。
                   3、SAS在处理 first / last 变量时,对组内每个观测行隐性地生成了一个first 和 一个last 变量,组内第一行first.var=1,last.var=0,...,最后一行 first.var=0,last.var=1,相应的,该组内如果只有一行观测,那么 first.var=1,last.var=1,例如:

                    ***创建数据;
                    DATA ONE;
                       INPUT SUBJECT SCORE;
                    DATALINES;
                    11
                    21
                    31
                    12
                    41
                    13
                    22
                    42
                    43
                    ;

                    ***1.对数据进行排序;
                    PROC SORT DATA=ONE;
                    BY SUBJECT;
                    RUN;

                    ***2.创建FIRST. 和LAST. 临时变量;
                    DATA TWO;
                       SET ONE;
                       BY SUBJECT;
                       FIRST = FIRST.SUBJECT;
                       LAST = LAST.SUBJECT;
                    RUN;
                                                   

                 4、当by 多个变量时,如两个:by var1 var2,SAS则分别以var1组和var2组生成first.var1、last.var1 和 first.var2、last.var2 变量:

DATA surgery;
   INFORMAT PID VID $1.;
   INPUT PID VID;
DATALINES;
1 A
1 B
1 B
1 C
2 D
2 D
2 E
;
PROC SORT DATA=surgery;
   BY PID VID;
RUN;

DATA sur;
   SET surgery;
   BY PID VID;
   FIRST_PID = FIRST.PID;
   LAST_PID = LAST.PID;
   FIRST_VID = FIRST.VID;
   LAST_VID = LAST.VID;

PROC PRINT DATA=sur;
   TITLE "Listing of Data Set sur";
RUN;

ObsPIDVIDFIRST_PIDLAST_PIDFIRST_VIDLAST_VID
11A1011
21B0010
31B0001
41C0111
52D1010
62D0001
72E0111



因字数限制,解决办法见回答。






无标题2.png
stata SPSS
vivienly121 学生认证  发表于 2018-1-11 18:21:47 |显示全部楼层
本帖最后由 vivienly121 于 2018-1-11 18:39 编辑

    三、解决办法:
            问题解析:目的是想实现 第一个病人的第一次就诊时的手术标识为1,第二次就诊时的手术标识为2,....,第n次就诊时的手术标识为n。
            步骤一:这时不仅有病人这个组,还有就诊这个组,而且我们可以观察到,当FIRST_PID=1时就是这个病人的第一条手术记录,当FIRST_PID=0,FIRST_VID=1时是这个病人其他后续就诊中的第一条手术记录,此时,这条记录的手术标识应该=上一次就诊的手术标识+1,即:
    /*手术次序1*/
proc sort data=surgery;
by PID VID;
run;

data surgery_ord;
set surgery;
by PID VID;
first_PID=first.PID;
first_VID=first.VID;
if first.PID  then surgery_order=1;
else if first.VID then surgery_order=surgery_order+1;
run;

proc print data=surgery_ord;
run;
Obs        PID        VID        first_PID        first_VID        surgery_order
1        1        A        1        1        1
2        1        B        0        1        .
3        1        B        0        0        .
4        1        C        0        1        .
5        2        D        1        1        1
6        2        D        0        0        .
7        2        E        0        1        .

         但结果还不是我们想要的,因为SAS开始处理每一行时,都会将变量初始化为缺失,所以在处理第二行first_PID=0,first_VID=1数据时,surgery_order为缺失,所以进行surgery_order=surgery_order+1,结果仍为缺失。此时可以利用retain语句,避免surgery_order被初始化。所以就需要步骤二。

         步骤二:解法一:其他同次就诊中的手术标识与该次就诊中的第一条记录相同,所以结合retain语句,可以将问题以如下方式解决:

/*手术次序2*/
proc sort data=surgery;
by PID VID;
run;

data surgery_ord;
set surgery;
retain surgery_order;
by PID VID;
first_PID=first.PID;
first_VID=first.VID;
if first.PID  then surgery_order=1;
else if first.VID then surgery_order=surgery_order+1;
run;

proc print data=surgery_ord;
run;

Obs        PID        VID        surgery_order        first_PID        first_VID
1        1        A        1        1        1
2        1        B        2        0        1
3        1        B        2        0        0
4        1        C        3        0        1
5        2        D        1        1        1
6        2        D        1        0        0
7        2        E        2        0        1


       无标题1.png
也可以不使用retain语句,而是将surgery_order变量放在累加语句中使用,累加语句中的变量不会被初始化,作用类似retain:

/*手术次序2*/
proc sort data=surgery;
by PID VID;
run;

data surgery_ord;
set surgery;
by PID VID;
first_PID=first.PID;
first_VID=first.VID;
if first.PID  then surgery_order=1;
else if first.VID then surgery_order+1;
run;

proc print data=surgery_ord;
run;

Obs         PID         VID         first_PID         first_VID         surgery_order
1        1        A        1        1        1
2        1        B        0        1        2
3        1        B        0        0        2
4        1        C        0        1        3
5        2        D        1        1        1
6        2        D        0        0        1
7        2        E        0        1        2

如果对累加语句不好理解,可以查看以下代码:

data surgery_ord;
set surgery;
by PID VID;

PUT "Before the process statement:  " _ALL_;

if first.PID  then surgery_order=1;
else if first.VID then surgery_order+1;

PUT "after the process statement:  " _ALL_/;
run;

无标题2.png


可以看到,累加语句中,surgery_ord这个变量是不会被初始化的。





回复

使用道具 举报

您需要登录后才可以回帖 登录 | 我要注册

GMT+8, 2018-7-20 11:04