SAS中文论坛

 找回密码
 立即注册

扫一扫,访问微社区

查看: 1604|回复: 10
打印 上一主题 下一主题

请教诸位:

[复制链接]

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
楼主
 楼主| 发表于 2010-2-24 08:24:51 | 只看该作者

请教诸位:

data myData;
input id    start    stop    drug $;
datalines;
1        0    1514    ZIDO
1       31     214    ZALC
1     1339    1346    DIDA
1     1400    1431    LAMI
1     1431    1826    LAMI
1     1857    3113    LAMI
1     2102    2410    SAQU
1     2410    3113    INDI
1     3113    3193    NELF
1     3113    5721    ABAC
1     3113    7201    EFAV
1     3193    3285    NELF
1     3285    3621    STAV
1     3285    5721    LAMI
1     3705    7201    KALE
2        0     699    LAMI
2        0    2280    ZIDO
2      214     699    STAV
2      214    2387    INDI
2     1305    1472    LAMI
2     1305    1472    ABAC
2     1305    1472    NELF
2     1879    1918    STAV
2     1879    1918    LAMI
2     1879    1918    KALE
2     1907    1956    STAV
2     1907    1956    LAMI
2     1926    1956    EFAV
2     1926    1956    TENO
2     2229    2234    SAQU
2     2229    2234    STAV
2     2229    2234    DIDA
2     2229    2234    TENO
2     2229    2234    ATAZ
2     2306    3571    LAMI
2     2306    4613    DIDA
2     2320    4613    NELF
run;

/*----------------------------------------------------*/
病人(ID)吃药(drug)。从某一点开始的天数(start)和停止(stop)。
如果在某一时间段上,病人同时吃至少三种不同的药,我们定为有效时间间隔。我想算出这个有效时间间隔(第一个即可,如果不止一个的话)的起始点(t1)和终点(t2)。
可以肯定的说这个起始点t1 即为某个start,t2 即为某个stop。
这是我的实际的数据中任意截取的,可能没有代表性。所以没有这个间隔也很正常。
还有:如果同一种药,第二次开的必须要等到第一次开的结束。
手算的不算。开个玩笑。
我琢磨了半天也没有想出好的方法。
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
沙发
 楼主| 发表于 2010-2-24 11:47:03 | 只看该作者

Re: 请教诸位:

如果同一种药的区间不交合的话,
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
板凳
 楼主| 发表于 2010-2-24 12:37:17 | 只看该作者

Re: 请教诸位:

真牛 <!-- s:shock: --><img src="{SMILIES_PATH}/icon_eek.gif" alt=":shock:" title="Shocked" /><!-- s:shock: -->
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
地板
 楼主| 发表于 2010-2-24 14:00:26 | 只看该作者

Re: 请教诸位:

先表示感谢。真是很好啊。
***JingJu*****
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
5#
 楼主| 发表于 2010-2-24 22:23:45 | 只看该作者

Re: 请教诸位:

谢谢猪兄(弟),非常妙。费了半天去理解。真是可谓,大山就是比土包高。再想想问一下
1. view在这里的作用什么呢?
2.有没有办法把t1-t2之间吃的药列出来,比如drugs = NELF/ABAC/EFAV...
原因是真正的有效是要至少三个药,而且他们需要从两个不同的类型里来的
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
6#
 楼主| 发表于 2010-2-25 00:25:32 | 只看该作者

Re: 请教诸位:

你为什么要做这么难的事情?
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
7#
 楼主| 发表于 2010-2-25 01:52:58 | 只看该作者

Re: 请教诸位:

非常感谢。在这里药物的分类有些复杂。所以我干脆就把吃药的历史按照每一次的药物变化而分隔开来。

[code:22uti9ru]data new;
        set jingju;        by id;
        length start stop 8 drugs  $100 lagdrug $4;/*drugs=drug list*/
        retain drugs;
        lagdrug = lag(drug); lagdate = lag(date); lagtype = lag(type);
        if first&#46;id then drugs = '';
        start = lagdate; stop = date;
        if lagtype = 'L' then drugs =        cats(drugs, '/', lagdrug);
                else if lagtype = 'R' then drugs = tranwrd(drugs, lagdrug, '');
                /*remove unncessary '/'s*/
        drugs = compress(drugs);
        if first(drugs) = '/' then drugs = substrn(drugs, 2);
        if first(left(reverse(drugs))) = '/' then drugs = substrn(drugs, 1, length(drugs)-1);
        drugs = tranwrd(drugs, '//', '/');       
        if ^first&#46;id;
        keep id start stop drugs;
run;[/code:22uti9ru]

运行结果如下:
Obs    id    start    stop    drugs

   01     1        0000      0031    ZIDO
   02     1       0031     0214    ZIDO/ZALC
   03     1      0214    1339    ZIDO
   04     1     1339    1346    ZIDO/DIDA
   05     1     1346    1400    ZIDO
   06     1     1400    1431    ZIDO/LAMI
   07     1     1431    1431    ZIDO
   08     1     1431    1514    ZIDO/LAMI
   09     1     1514    1826    LAMI
10     1     1826    1857
11     1     1857    2102    LAMI
12     1     2102    2410    LAMI/SAQU
13     1     2410    2410    LAMI
14     1     2410    3113    LAMI/INDI
15     1     3113    3113    INDI
16     1     3113    3113
17     1     3113    3113    NELF
18     1     3113    3113    NELF/ABAC
19     1     3113    3193    NELF/ABAC/EFAV
20     1     3193    3193    ABAC/EFAV
21     1     3193    3285    ABAC/EFAV/NELF
22     1     3285    3285    ABAC/EFAV
23     1     3285    3285    ABAC/EFAV/STAV
24     1     3285    3621    ABAC/EFAV/STAV/LAMI
25     1     3621    3705    ABAC/EFAV/LAMI
26     1     3705    5721    ABAC/EFAV/LAMI/KALE
27     1     5721    5721    EFAV/LAMI/KALE
28     1     5721    7201    EFAV/KALE
29     1     7201    7201    KALE
再次感谢。除掉你不凡的编程技巧,把start和stop排成一行,是关键。
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
8#
 楼主| 发表于 2010-2-25 10:55:54 | 只看该作者

Re: 请教诸位:

I wish this simplified approach helps (or at least addresses the problem at all). The output may be refined to meet the requirement more specific. E.g., some rows in the output can be further combined with duplicated items removed, etc., if desired. <!-- s:-) --><img src="{SMILIES_PATH}/icon_smile.gif" alt=":-)" title="Smile" /><!-- s:-) -->

[code:2h9ay8o8]proc sql;
  create table myData as
    select *,
           monotonic() as rowID
      from myData
      order by id,
               start,
               stop,
               drug;
quit;

proc sql;
  create table semi_final as
    select a&#46;id,
           max(a&#46;start, b&#46;start, c&#46;start) as start,
           min(a&#46;stop, b&#46;stop, c&#46;stop) as stop,
           trim(a&#46;drug) || '/' || trim(b&#46;drug) || '/' || trim(c&#46;drug) as drugs
      from myData as a,
           myData as b,
           myData as c
      where a&#46;rowID &lt; b&#46;rowID &lt; c&#46;rowID and
            a&#46;id = b&#46;id = c&#46;id and
            a&#46;drug ^= b&#46;drug and b&#46;drug ^= c&#46;drug and a&#46;drug ^= c&#46;drug and
            max(a&#46;start, b&#46;start, c&#46;start) &lt;= min(a&#46;stop, b&#46;stop, c&#46;stop)
      order by a&#46;id,
               calculated start,
               calculated stop,
               calculated drugs;
quit;

data final(drop = drugs i
           rename = (final_drugs = drugs)
          );
  set semi_final;
  by id
     start
     stop
     drugs;

  retain final_drugs;
  length final_drugs $200;

  if first&#46;stop then final_drugs = drugs;

  do i = 1 to 3;
    if index(final_drugs, strip(scan(drugs, i, '/'))) = 0 then final_drugs = strip(final_drugs) || '/' || strip(scan(drugs, i, '/'));
  end;

  if last&#46;stop then output;
run;[/code:2h9ay8o8]
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
9#
 楼主| 发表于 2010-2-25 23:02:49 | 只看该作者

Re: 请教诸位:

回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
10#
 楼主| 发表于 2010-2-26 02:20:33 | 只看该作者

Re: 请教诸位:

猪头兄弟(假设不是非常规的姐妹):
刚才我还想温习你经典的代码,不料。。。呜呼哀哉。真可谓,代码不知何处去,猪头依旧在那里。。。
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-2-6 09:51 , Processed in 0.069963 second(s), 20 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

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