SAS中文论坛

标题: 如何找数据中某些观测的(有附加条件的)前一个观测并计数 [打印本页]

作者: shiyiming    时间: 2009-9-16 04:50
标题: 如何找数据中某些观测的(有附加条件的)前一个观测并计数
有这样一组数据, 已经按ID 和 date 排好顺序。

ID        date        A        B         C        Nr
001        2003.12        0        1        1        1
001        2005.9        1        4        1        2
002        2004.12        0        2        1        3
002        2006.3        1        3        0        4
002        2007.12        1        5        0        5
002        2008.12        1        3        0        6
003        2006.6        1        1        0        7
004        2004.12        0        6        1        8
004        2008.12        1        5        0        9




真实数据几十万行,没有 ”Nr”(序号) 这一列,为了叙述方便,加了这一列。

要求:1)如果A=1, 就要找到与这一行相同ID的前一行观测, 如:Nr. 2 的A=1, 它的前一观测应为Nr.1, 又如:Nr. 7 的A=1, 但它没有与它相同ID 的前一观测。
2)如果在第一步中找到的前一观测的B=5, 那么这一观测将忽略不计,而找它的前一观测且B不等于5才算找到。如:Nr. 6 的前一观测应为Nr.5, 而Nr.5的B=5, 所以Nr.6 的前一观测实际应为 Nr.4。
3)按照上面两步的要求全部找到前一观测后,将该观测的C值与前一观测的C值进行比较,C的取值只有0和1,如果两个观测的C相同,那么不计数,如果两个观测的C值不同,就把它算作一个并计数,最后计算出整个数据中一共存在多少个这样的观测(它的C值与前一观测的C值不同)。
作者: shiyiming    时间: 2009-9-16 10:31
标题: Re: 如何找数据中某些观测的(有附加条件的)前一个观测并计数
不太明白,如果只要结果不要过程的话,把B=5的观测去掉,问题就简单多了
[code:2bufe6jp]data raw;
        input ID date $ A B C Nr;
datalines;
001 2003.12 0 1 1 1
001 2005.9 1 4 1 2
002 2004.12 0 2 1 3
002 2006.3 1 3 0 4
002 2007.12 1 5 0 5
002 2008.12 1 3 0 6
003 2006.6 1 1 0 7
004 2004.12 0 6 1 8
004 2008.12 1 5 0 9
;

data temp;
        set raw(where=(b ne 5));
        by id;
        lag_c=lag(c);
        if first.id=0 then
                do;
                        bxor_c=bxor(c,lag_c);
                        if bxor_c=1 then output;
                end;
run;

data _null_;
        dsid=open('temp','i');
        n=attrn(dsid,'nobs');
        put "*** " n "***";
run;[/code:2bufe6jp]
作者: shiyiming    时间: 2009-9-16 17:42
标题: Re: 如何找数据中某些观测的(有附加条件的)前一个观测并计数
data step and lag function...........
作者: shiyiming    时间: 2009-9-16 20:26
标题: Re: 如何找数据中某些观测的(有附加条件的)前一个观测并计数
[quote:3cug7hli]...如果只要结果不要过程的话,把B=5的观测去掉,问题就简单多了[/quote:3cug7hli]

如果此处B=5而且A=1。此观测应用于寻找它的前一次观测值,而不是简单的删除.
作者: shiyiming    时间: 2009-9-16 22:06
标题: Re: 如何找数据中某些观测的(有附加条件的)前一个观测并计数
<!-- s:( --><img src="{SMILIES_PATH}/icon_sad.gif" alt=":(" title="Sad" /><!-- s:( -->  那位大侠有好主意指点一下吧
作者: shiyiming    时间: 2009-9-17 02:13
标题: Re: 如何找数据中某些观测的(有附加条件的)前一个观测并计数
[b:22d4x75w]感谢hopewell 和byes 两位Experts [/b:22d4x75w]的回复。

hopewell 的答案没有把第一条的要求考虑进去。所以显得很简单。也可能是在叙述要求是没表述清楚,我在试一下:

不是找每一行观测的前一个任意的观测。用lag是可以找到前一观测,但它的ID必须和这一观测的ID相同才可以,如果不同,等于没有前一观测,用缺失表示。

还使用sas说话吧,一目了然。 下面这段运用了hopewell的主意,顺便说一句:[b:22d4x75w][u:22d4x75w]HOPEWELL你真棒[/u:22d4x75w][/b:22d4x75w]。


data Basis;
        set raw end=endf;
        retain ii;
                if first.id=0 then
                        do;       
                                lag_c=lag(c);
                                if a=1 then do;       
                                bxor_c=bxor(c,lag_c);
                         if bxor_k =1 then ii+1;
                     end;
        end;
        if endf then put ii;
run;
解决了上述问题,但是没能解决B=5 这项。
向所有参与探讨的人致敬。
作者: shiyiming    时间: 2009-9-17 07:10
标题: Re: 如何找数据中某些观测的(有附加条件的)前一个观测并计数
[code:lr2k0my0]
data raw;
   input ID date $ A B C Nr;       
datalines;
001 2003&#46;12 0 1 1 1
001 2005&#46;9 1 4 1 2
001 1234&#46;4 1 1 1 1
002 2004&#46;12 0 2 1 3
002 2006&#46;3 1 3 0 4
002 2007&#46;12 1 5 0 5
002 2008&#46;12 1 3 0 6
003 2006&#46;6 1 1 0 7
004 2004&#46;12 0 6 1 8
004 2008&#46;12 1 5 0 9
005 2004&#46;12 0 2 1 3
005 2006&#46;3 1 3 0 4
005 2007&#46;12 1 5 0 5
005 2008&#46;12 1 3 0 6
005 2006&#46;6 1 1 0 7
005 2004&#46;12 0 6 1 8
005 2008&#46;12 1 5 0 9
006 2003&#46;12 0 1 1 1
006 2005&#46;9 1 4 1 2
006 1234&#46;4 1 1 1 1
006 2004&#46;12 0 2 1 3
006 2006&#46;3 1 3 0 4
006 2007&#46;12 1 5 0 5
006 2008&#46;12 1 3 0 6
006 2006&#46;6 1 1 0 7
006 2004&#46;12 0 6 1 8
006 2008&#46;12 1 5 0 9
006 2004&#46;12 0 2 1 3
006 2006&#46;3 1 3 0 4
006 2007&#46;12 1 5 0 5
006 2008&#46;12 1 3 0 6
006 2006&#46;6 1 1 0 7
006 2004&#46;12 0 5 1 8
006 2008&#46;12 1 5 0 9
;
;
run;

data temp;
   set raw;
   by id;
   retain a1 b1 c1 &#46;;
        if first&#46;id then do;
                if b ^=5 then do;
                        a1=a; b1=b; c1=c;
                end;
                delete;
        end;         
   if a=1 and b1 ^=5 then do;
                output;
           if b ^=5 then do;
                        a1=a; b1=b; c1=c;           
                end;
        end;
        else if b ^=5 then do;
           a1=a; b1=b; c1=c;
           delete;
        end;

run;

data temp1;
        set temp end=endof;
        if ^missing(c1) then if c ^=c1 then count+1;
        if endof then put '# of interested obs=' count;

run;

proc print;run;
[/code:lr2k0my0]
第一code未必对;第二code即使对,也不简练。我感觉我的测试数据没有代表性。A B C 为需要前一观测的观测;A1 B1 C1 为前一观测。
作者: shiyiming    时间: 2009-9-17 11:18
标题: Re: 如何找数据中某些观测的(有附加条件的)前一个观测并计数
[code:2f7cgwfo]data ahuige;
    input ID$ date A B C Nr;
    cards;
001 2003&#46;12 0 1 1 1
001 2005&#46;9 1 4 1 2
002 2004&#46;12 0 2 1 3
002 2006&#46;3 1 3 0 4
002 2007&#46;12 1 5 0 5
002 2008&#46;12 1 3 0 6
003 2006&#46;6 1 1 0 7
004 2004&#46;12 0 6 1 8
004 2008&#46;12 1 5 0 9
;
run;

data final(drop=prevC prevID);
    set ahuige;
    retain prevC prevID;
    if a=1 and prevID=id then if c^=prevC then flag=1;
    if  b^=5 then        do;  prevID=id; prevC=c; end;
    totalflagnum+flag;
run;[/code:2f7cgwfo]
作者: shiyiming    时间: 2009-9-17 12:47
标题: Re: 如何找数据中某些观测的(有附加条件的)前一个观测并计数
<!-- s:lol: --><img src="{SMILIES_PATH}/icon_lol.gif" alt=":lol:" title="Laughing" /><!-- s:lol: --> ahuige 大师出手了,又在跟jingju11比看谁写的最短呢吧
大概看懂了,唬的我还以为加个prev前缀就能自动赋值呢 <!-- s:o --><img src="{SMILIES_PATH}/icon_surprised.gif" alt=":o" title="Surprised" /><!-- s:o -->
[code:3e8xbcc0]data final;
    set ahuige;
    retain prevC prevID;
        /* 先判断,后retain值 */
    if a=1 and prevID=id then if c^=prevC then flag=1; /* 在id组内a值为1时,判断条件,计数变量加1 */
    if  b^=5 then      /* 在b不等于5的情况下retain变量c和id的值 */  
                do;  
                        prevID=id;
                        prevC=c;
                end;
    totalflagnum+flag; /* 求总计 */
run;[/code:3e8xbcc0]




欢迎光临 SAS中文论坛 (https://mysas.net/forum/) Powered by Discuz! X3.2