SAS中文论坛

 找回密码
 立即注册

扫一扫,访问微社区

查看: 1892|回复: 12
打印 上一主题 下一主题

一个问题

[复制链接]

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
楼主
 楼主| 发表于 2010-8-19 03:20:37 | 只看该作者

一个问题

data had;
  input id day status; datalines;
  1 0 0
  1 1 0
  1 2 1
  1 3 0
  1 4 1
  1 5 1
  2 0 1
  2 1 0
  2 2 1
  2 3 0
  2 4 1
  2 5 1
  2 6 0
  3 0 1
  3 1 1
  3 2 0
  4 0 0
  4 1 0
  4 2 1
  4 3 0
  ;
*the resulting data set should be:
[quote:14y5mvye]id censored Time2Event
1  0              4
2  0              4
3  0              0
4  1              3[/quote:14y5mvye]--------------------------
至少两个或以上连续的status=1即为一个事件,此时censor=0 ,Time2Event = day (第一个status=1在 >=2连续的status=1中)-day(开始,为了方便,在这里总为0) ---(比如id 1 2);
如果没有此类事件发生那么censor=1 ,Time2Event = day (最后一个观察)-day(开始, 0) (比如id 4)
如果从开始就是事件,那么censor=0 ,Time2Event = 0 (比如id 3)
怎么做比较简洁呢?
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
沙发
 楼主| 发表于 2010-8-19 07:29:53 | 只看该作者

Re: 一个问题

[quote:3injbw6j]至少两个或以上连续的status=1即为一个事件[/quote:3injbw6j]
在一个id里会有多个事件吗? 比如下面这样
1 0 0
1 1 1
1 2 1
1 3 0
1 4 1
1 5 1
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
板凳
 楼主| 发表于 2010-8-19 08:29:46 | 只看该作者

Re: 一个问题

很有经验啊。你所提的是生存分析之中的多事件分析。其实说白了应该有三种情况,first event, blip, and relapse.

比如说 0 0 1 1 0 1 1 1--》前两个0是无事件,下来两个 1 1 是 1st 事件, 接着的 0 是 blip,然后就是relapse。
在这里我先简化成 time to first event 也就是只感兴趣第一个事件。
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
地板
 楼主| 发表于 2010-8-19 20:14:26 | 只看该作者

Re: 一个问题

相当的不简洁  <!-- s:( --><img src="{SMILIES_PATH}/icon_sad.gif" alt=":(" title="Sad" /><!-- s:( -->
9.2下有效
鸣谢ahuige的赞助
[code:2fokac2l]data had;
        input id day status;
datalines;
1 0 0
1 1 0
1 2 1
1 3 0
1 4 1
1 5 1
2 0 1
2 1 0
2 2 1
2 3 0
2 4 1
2 5 1
2 6 0
3 0 1
3 1 1
3 2 0
4 0 0
4 1 0
4 2 1
4 3 0
5 0 0
5 1 1
5 2 1
5 3 0
5 4 1
5 5 1
;
/*proc sort*/
data out(drop=status_list&#58; i position length lag_type first_event_flag);
        length status_list $500 type $1;
        do _n_=1 by 1 until(last&#46;id);
                set had;
                by id;
                status_list=cats(status_list,put(status,1&#46;));
        end;
        status_list=translate(status_list,',','0');
        event_count=0;
        do i=1 to count(status_list,',')+1;
                status_list_part=scan(status_list,i,',','m');
                if status_list_part='1' then do;
                        call scan(status_list,i,position,length,',','m');
                        substr(status_list,position,length)='D';
                end;
                else if not missing(status_list_part) then do;
                        first_event_flag=min(first_event_flag,i);
                        event_count+1;
                end;
        end;
        if not missing(first_event_flag) then do;
                call scan(status_list,first_event_flag,position,length,',','m');
                substr(status_list,position,length)=repeat('F',length);
        end;
        status_list=translate(status_list,'D',',','R','1');
        group=1;
        do _n_=1 to _n_;
                set had;
                type=substr(status_list,_n_,1);
                lag_type=lag(type);
                if _n_ gt 1 then do;
                        if lag_type ne type then group+1;
                end;
                output;
        end;
run;
data out(keep=type id censor time2event);
        do _n_=1 by 1 until(last&#46;group);
                set out;
                by id group;
                if _n_=1 then start=day;
        end;
        if type in('F','R') then do;
                censor=0;
                if group=1 then time2event=0;
                else time2event=start-0;
        end;
        else if type='D' then do;
                censor=1;
                time2event=day-0;
        end;
        if type in('F','R') or event_count=0;
run;[/code:2fokac2l]
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
5#
 楼主| 发表于 2010-8-19 22:05:17 | 只看该作者

Re: 一个问题

让我慢慢理解消化。
不过看到你回复程序是如此之长,我才有所意识, 难道这个问题很复杂吗?
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
6#
 楼主| 发表于 2010-8-20 03:53:55 | 只看该作者

Re: 一个问题

你们两个版主倒是蛮亲热的啊
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
7#
 楼主| 发表于 2010-8-20 04:52:51 | 只看该作者

Re: 一个问题

唔。思路是如此的流畅啊!
我这个假版主该卸任了。
我也该去烧烧香拜拜佛来平息我此时的嫉妒心思了。
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
8#
 楼主| 发表于 2010-8-20 08:08:42 | 只看该作者

Re: 一个问题

我又没看到老猪的代码 <!-- s:oops: --><img src="{SMILIES_PATH}/icon_redface.gif" alt=":oops:" title="Embarassed" /><!-- s:oops: -->
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
9#
 楼主| 发表于 2010-8-20 10:54:19 | 只看该作者

Re: 一个问题

[code:3rosb17v]data final(keep=id censor Time2event);
    set had ;
    by id day;
    retain censor 1 lstatus lday Time2Event 0;
    censor =min( 1-min(status,lstatus) ,max(first&#46;id,censor));
    if (1-censor) and not Time2Event or last&#46;id and censor then  Time2Event =max(lday,(last&#46;id and censor)*day );
    if last&#46;id then output;
    time2Event=time2Event*(1-last&#46;id);
    if  status=1 and lstatus=0 then lday=day;
    lstatus=status*(1-last&#46;id);
run;[/code:3rosb17v] 相好的。哪里跑?
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
10#
 楼主| 发表于 2010-8-20 11:38:08 | 只看该作者

Re: 一个问题

to ahuige:
我已经稳获代码长度第一了,别的第一我就不争了
by the way, 怪不得某人能看到飞碟,难说那飞碟是不是他招来的呢 <!-- s:lol: --><img src="{SMILIES_PATH}/icon_lol.gif" alt=":lol:" title="Laughing" /><!-- s:lol: -->

看的相当晕,等清醒点再看看 <!-- s:( --><img src="{SMILIES_PATH}/icon_sad.gif" alt=":(" title="Sad" /><!-- s:( -->
[code:fo685sf0]data final;
        set had;
        by id day;

/*        retain同时赋初值,lstatus为by组内上条obs中status的值,lday为by组内上条obs中day的值*/
        retain censor 1 lstatus lday Time2Event 0;

/*        以下部分计算censor,time2event*/
/*        1、计算censor的值*/
/*                (1) 1-min(status,lstatus):当本条obs与上条obs status的值不同时,值为1,相同时为0*/
/*                (2) max(first&#46;id,censor):by组开始时,强制值为1,其他时候取上条obs的censor的值*/
/*                (3) min(a,b):因为取min,必须a,b两部分同时为1的时候才为1,通过censor的滞后判断event的结束或延续*/
        censor=min(1-min(status,lstatus),max(first&#46;id,censor));
/*        2、计算time2event的值*/
/*                (1) 条件部分:*/
/*                        a (1-censor) and (1-Time2Event):censor=0(event发生) and time2event=0(first event)的时候*/
/*                        b last&#46;id and censor:by组末尾 and censor=1(event未发生)的时候*/
/*                (2) 计算部分:*/
/*                        a 判断 last&#46;id and censor:(event未发生)保持day的值,否则置0*/
/*                        b max(lday,day):取最大值*/
        if (1-censor) and (1-Time2Event) or last&#46;id and censor then  
                Time2Event =max(lday,(last&#46;id and censor)*day );

/*        在每个by组的末尾output*/
        if last&#46;id then output;

/*        计算部分结束,设置滞后值开始*/

/*        以下部分获取滞后值,在by组结尾重置变量为初值*/
/*        1、仅在每个by组的末尾,重置Time2Event的值为0*/
        time2Event=time2Event*(1-last&#46;id);
/*        2、当疑似event开始时,将当前观测day的值赋给lday*/
        if status=1 and lstatus=0 then lday=day;
/*        3、将当前观测status的值赋给lstatus,仅在每个by组的末尾,重置lstatus的值为0*/
        lstatus=status*(1-last&#46;id);

run;[/code:fo685sf0]
回复 支持 反对

使用道具 举报

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

本版积分规则

QQ|小黑屋|手机版|Archiver|SAS中文论坛  

GMT+8, 2026-2-4 01:32 , Processed in 0.071973 second(s), 20 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表