全部版块 我的主页
论坛 数据科学与人工智能 数据分析与数据科学 SAS专版
7941 3
2018-01-11
总结一、通过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

原图尺寸 26.05 KB

无标题2.png

二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

全部回复
2018-1-11 18:21:47
三、解决办法:
            问题解析:目的是想实现 第一个病人的第一次就诊时的手术标识为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这个变量是不会被初始化的。





二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2018-12-6 14:47:17
感谢楼主分享
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2019-1-24 22:53:02
学习了
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

相关推荐
栏目导航
热门文章
推荐文章

说点什么

分享

扫码加好友,拉您进群
各岗位、行业、专业交流群