首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何计算SAS中的最大连续值数

如何计算SAS中的最大连续值数
EN

Stack Overflow用户
提问于 2020-11-02 06:38:51
回答 2查看 441关注 0票数 2

我有一个数据集,每个病人有一行,它包含关于病人服用11次药物的日期(格式化为SAS日期)的信息。在数据集中,每天最多有一剂药物。患者可以在1到11剂量之间的任何地方确定日期,而且没有中间剂量缺少信息(例如,如果Dose5被填充,定义为Dose1-Dose 4被填充)。我感兴趣的是病人连续服用一剂药的最长天数。这里有5行数据样本。

代码语言:javascript
复制
data have;
    input PATIENT_ID Dose1 :ddmmyy10. Dose2 :ddmmyy10. Dose3 :ddmmyy10. Dose4 :ddmmyy10. Dose5 :ddmmyy10. Dose6 :ddmmyy10. Dose7 :ddmmyy10. Dose8 :ddmmyy10. Dose9 :ddmmyy10. Dose10 :ddmmyy10. Dose11;
    format Dose1 Dose2 Dose3 Dose4 Dose5 Dose6 Dose7 Dose8 Dose9 Dose10 Dose11 ddmmyy10.;
    cards;
          1          01/01/2020 01/02/2020 01/03/2020 01/04/2020 01/05/2020 01/06/2020 01/07/20  1/08/2020 01/09/2020 01/10/2020 01/11/2020
          2          01/01/2020 01/02/2020 01/03/2020 01/05/2020 01/06/2020
          3          01/02/2020 01/04/2020 01/06/2020 01/08/2020 01/10/2020 01/12/2020 01/14/2020 01/16/2020 01/18/2020
          4          01/03/2020 01/04/2020 01/05/2020 01/06/2020 01/07/2020 01/08/2020 01/09/2020  1/10/2020 01/12/2020 01/13/2020
          5          01/01/2020 01/07/2020 01/08/2020 01/10/2020
;
run;

我想得到变量MAX_CONSECUTIVE_DAYS:

代码语言:javascript
复制
data want;
    input PATIENT_ID MAX_CONSECUTIVE_DAYS Dose1 :ddmmyy10. Dose2 :ddmmyy10. Dose3 :ddmmyy10. Dose4 :ddmmyy10. Dose5 :ddmmyy10. Dose6 :ddmmyy10. Dose7 :ddmmyy10. Dose8 :ddmmyy10. Dose9 :ddmmyy10. Dose10 :ddmmyy10. Dose11;
    format Dose1 Dose2 Dose3 Dose4 Dose5 Dose6 Dose7 Dose8 Dose9 Dose10 Dose11 ddmmyy10.;
    cards;
          1          11                  01/01/2020 01/02/2020 01/03/2020 01/04/2020 01/05/2020 01/06/2020 01/07/20  1/08/2020 01/09/2020 01/10/2020 01/11/2020
          2          3                   01/01/2020 01/02/2020 01/03/2020 01/05/2020 01/06/2020              
          3          1                   01/02/2020 01/04/2020 01/06/2020 01/08/2020 01/10/2020 01/12/2020 01/14/2020 01/16/2020 01/18/2020
          4          8                   01/03/2020 01/04/2020 01/05/2020 01/06/2020 01/07/2020 01/08/2020 01/09/2020  1/10/2020 01/12/2020 01/13/2020
          5          2                   01/01/2020 01/07/2020 01/08/2020 01/10/2020
run;

到目前为止,我只能想出如何用蛮力零碎地做这件事。

代码语言:javascript
复制
data bruteforce;
    set have;
    if Dose2 =. then MAX_CONSECUTIVE_DAYS=1;
      else if Dose3=. then
      do;
        if Dose2-Dose1=1 then MAX_CONSECUTIVE_DAYS=2;
          else MAX_CONSECUTIVE_DAYS=1;
      end;
      else if Dose4=. then
      do;
        if Dose3-Dose1=2 then MAX_CONSECUTIVE_DAYS=3;
          else if (Dose2-Dose1=1) or (Dose3-Dose2=1) then MAX_CONSECUTIVE_DAYS=2;
          else MAX_CONSECUTIVE_DAYS=1;
      end;
      else if Dose5=. then
      do;
        if Dose4-Dose1=3 then MAX_CONSECUTIVE_DAYS=4;
          else if (Dose3-Dose1=2) or (Dose4-Dose2=2) then MAX_CONSECUTIVE_DAYS=3;
          else if (Dose2-Dose1=1) or (Dose3-Dose2=1) or (Dose4-Dose3=1) then MAX_CONSECUTIVE_DAYS=2;
          else MAX_CONSECUTIVE_DAYS=1;
      end;
     /*And so on and so forth until accounting for rows where Dose10 is populated*/
 run;

然而,在我的实际工作中,有超过200剂量的药物,所以用if-然后-else语句做一系列do循环是没有意义的。如果我不得不猜测,解决方案可能与数组有关,但我不知道从何处或如何开始。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-11-02 09:07:10

首先,谢谢你清楚地解释了你的问题和你迄今所做的努力:

只是一张纸条。我将您的输入数据更改为具有mmddyy10格式/格式的日期。我想你想要的是连续数数,而不是几个月。

不管怎样,试试这个。请随便问

代码语言:javascript
复制
data have;
infile datalines missover;
input PATIENT_ID (Dose1 - Dose11)(:mmddyy10.);
format Dose: mmddyy10.;
cards;
1 01/01/2020 01/02/2020 01/03/2020 01/04/2020 01/05/2020 01/06/2020 01/07/2020 1/08/2020 01/09/2020 01/10/2020 01/11/2020
2 01/01/2020 01/02/2020 01/03/2020 01/05/2020 01/06/2020
3 01/02/2020 01/04/2020 01/06/2020 01/08/2020 01/10/2020 01/12/2020 01/14/2020 01/16/2020 01/18/2020
4 01/03/2020 01/04/2020 01/05/2020 01/06/2020 01/07/2020 01/08/2020 01/09/2020 1/10/2020 01/12/2020 01/13/2020
5 01/01/2020 01/07/2020 01/08/2020 01/10/2020
;

data want(drop=c i);
   set have;
   array dose {*} Dose:;
   c = 1;
   do i = 2 to dim(dose);
      if dose[i] - dose[i-1] = 1 then c + 1;
      else do;
         if c > mc then mc = c;
         c = 1;
      end;
   end;
   if mc = . then mc = c;
run;

结果:

代码语言:javascript
复制
PATIENT_ID Dose1...Dose11 mc 
1 ... 11 
2 ... 3 
3 ... 1 
4 ... 8 
5 ... 2 
票数 2
EN

Stack Overflow用户

发布于 2020-11-02 11:01:40

正确,基于变量的array将允许您遍历日期并计算最长的运行时间。

提示:尽可能使用表示值内容的变量名。dose<n>的元信息比dose_date<n>少。

稳健的计算将检查或说明边缘情况,如没有剂量。

样本代码:

从数组中提取值需要很小的CPU成本(也许可以忽略不计)。假设数组名为x。循环内的计算x[index]-x[index-1]重复这样的代价。

例如:x[5]−[x4]x[6]−x[5]。将提取的值存储在变量中将减少重复成本。

Data选项keep=是要输出的变量的显式列表。或者,可以使用drop=_:来排除工人变量(在本示例中),其名称以_开头。

代码语言:javascript
复制
data have;
infile datalines missover; input 
ID X1-X11; format _numeric_ 4.; datalines;
1 01 02 03 04 05 06 07 08 09 10 11
2 01 02 03 05 06
3 02 04 06 08 10 12 14 16 18
4 03 04 05 06 07 08 09 10 12 13
5 01 07 08 10
6 01
7
8 01 03 05 07 09 11 13 15 17 19 21
;

data want(keep=id x: rl_max);
  set have;
  array X X:;

  if not missing(x1) then _rl = 1;  /* preset if not an edge case */
  _p = x1;

  rl_max = _rl;

  do _index = 2 to dim(X);
    _q = X[_index]; /* store extracted value in worker variable */
    if missing(_q) then leave; /* iterate as little as needed */
     
    if _q - _p = 1 then /* consecutive */
      _rl = sum (_rl, 1);
    else do; /* gap, check and reset */
      if _rl > rl_max then rl_max = _rl;
      _rl = 1;
    end;

    _p = _q;  /* current to previous */
  end;

  if _rl > rl_max then rl_max = _rl;   /* no gaps */
run;
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64640866

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档