将某个变量的连续观察值相加

Sum consecutive observations by some variable

我刚开始学习使用 SAS,请多多包涵。我有以下关于处方使用的样本患者数据,我想尝试结合观察来形成更多的患者故事,但保持时间表完整:

data have;
 input dose . id . supply date .;
 datalines;
 "5" 1234 30 01012015
 "10" 1234 30 02012015
 "10" 1234 30 03012015
 "5" 1234 30 04012015
 "2" 1234 30 05012015
 "5" 4321 30 07012016
 "2" 9876 30 05012016
 "2" 9876 30 06012016
 "10" 9876 30 07012016
 ;
run;

其中 dose 是以 mg 为单位的剂量,id 是患者 ID,supply 是药物供应的天数,date 是补充日期。

我想巩固一些观察结果,这样当我们查看患者 1234 时,我们可以看到他们服用 5 毫克 30 天,然后 10 毫克 60 天,然后再次服用 5 毫克 30 天,等等。我学到的所有求和和分组命令都会将观察结果 1 和观察结果 4 结合在一起,但患者的故事是剂量增加然后减少,我想保持原样但不知道如何保持。

所以它看起来像这样:

data want;
 input dose . id . supply date .;
 datalines;
 "5" 1234 30 01012015
 "10" 1234 60 02012015
 "5" 1234 30 04012015
 "2" 1234 30 05012015
 "5" 4321 30 07012016
 "2" 9876 60 05012016
 "10" 9876 30 07012016
 ;
run;

查看观察结果 3 汇总为 2、8 汇总为 7 等

如有任何提示,我们将不胜感激!

这是一个依赖于保留变量的解决方案。它只是众多中的一个,而且它使用了相当先进的技术,可能会吓到初学者。您已收到警告 ;)

使用 goto 和标签(以 : 结尾)不是很常见,在 大多数 情况下可以避免。但在这种情况下,似乎是有道理的,主要是为了简洁。

data have;
  informat id 4. dose 3. supply 3. date mmddyy8.;
  format date mmddyy10.;
  input id dose supply date;
  datalines;
1234  5 30 01012015
1234 10 30 02012015
1234 10 30 03012015
1234  5 30 04012015
1234  2 30 05012015
4321  5 30 07012016
9876  2 30 05012016
9876  2 30 06012016
9876 10 30 07012016
;

我们首先确保我们的数据正确排序。

proc sort data=have;
  by id date;
run;

解决方案

retain 语句将使声明的变量的值在数据步骤迭代 have 数据集的行时保存在内存中。

注意_i后缀是从have已有的变量加上的,i代表input.

data want(drop=id_i dose_i supply_i date_i);
  format id dose supply 8. date mmddyy10.;
  retain id dose supply date;
  set have(rename=(id=id_i dose=dose_i supply=supply_i date=date_i)) end=last;

  if _N_ = 1 then goto propagate;

  if id_i = id and dose_i = dose then do;
    supply = supply + supply_i;
    goto checklast;
  end;

  * When id or dose is different from previous row, ;
  * we write the observation to the want table.     ;
  output;

  propagate:
  id     = id_i;
  dose   = dose_i;
  supply = supply_i;
  date   = date_i;

  checklast:
  if last then output;
run;

这里有几点需要注意:

  • _N_是表示当前迭代次数的自动SAS变量
  • end=last(用作 set 语句的参数)创建一个名为 last 的变量(这是一个任意名称),该变量将取值 1当从 have 读取最后一个观察值时,否则 0。我们在数据步骤结束时将其用作布尔变量。
  • 请记住,在尝试解决这个问题时,数据步骤的功能就像一个 for 循环,遍历其源 table.
  • 的行

结果

id    dose   supply    date
1234    5       30    01/01/2015
1234    10      60    02/01/2015
1234    5       30    04/01/2015
1234    2       30    05/01/2015
4321    5       30    07/01/2016
9876    2       60    05/01/2016
9876    10      30    07/01/2016

另一种方法使用 NOTSORTED 选项,它不需要任何关于数据集的预定知识。

data have;
informat date mmddyy8.;
format date date9.;
 input dose  id $ supply date ;
 datalines;
5 1234 30 01012015
10 1234 30 02012015
10 1234 30 03012015
5 1234 30 04012015
2 1234 30 05012015
5 4321 30 07012016
2 9876 30 05012016
2 9876 30 06012016
10 9876 30 07012016
 ;
run;

proc sort data=have;
  by id date;
run;

data want;
set have;
by id dose notsorted;
retain n_days;

if first.dose or first.id then n_days=0;

n_days+supply;

if last.dose then output;

run;