填写顺序编号记录之间的间隙并更新状态指示符

时间:2016-07-15 00:09:26

标签: sas

在汇总数据集中,我在记录基线后的每个< num+1处都有status个事件。我也有hour该事件可能被记录下来。我想创建一个新数据集,其中每个last hour都有一条记录,从第一个到hour,每个记录的last hour是最后一个记录status的记录

以下是一个示例数据集:

status

在这种情况下,第一个记录的小时是第二个,最后记录的小时是第10个小时。记录数据的最后一小时是第12小时。

最终数据集应如下所示:

data new;
  input hour status last_hour;
  cards;
  2 1 12
  4 1 12
  5 1 12
  6 1 12
  7 0 12
  9 1 12
 10 0 12
;
run;

我有点使用这一系列的数据步骤,但我不确定是否有一种更清洁的方式我没有看到。

0 . 12
1 . 12
2 1 12
3 1 12
4 1 12
5 1 12
6 1 12
7 0 12
8 0 12
9 1 12
10 0 12
11 0 12
12 0 12

1 个答案:

答案 0 :(得分:1)

看到你的代码,你似乎没有忘记你还有id的事实。所以这是一个处理不同身份的新解决方案。请参阅下文,了解我的第一个忽略id的解决方案。

由于last_hour始终为12,因此我将其从have数据集中删除。它将在稍后添加。

data have;
  input id hour status;
  cards;
1 2 1
1 4 1
1 5 1
1 6 1
1 7 0
1 9 1
1 10 0
2 2 1
2 4 1
2 5 1
2 6 1
2 7 0
2 9 1
2 10 0
;

创建一个hours数据集,只包含数字0到12;

data hours;
  do i = 0 to 12;
    hour = i;
    output;
  end;
  drop i;
run;

创建一个临时数据集,该数据集具有正确的行数(每个id为13行,hour表中存在有效have值。

proc sql;
  create table tmp as
    select distinct t1.id, t2.hour, 12 as last_hour
      from have as t1

    cross join 

      (select hour from hours) as t2;
quit;

然后使用mergeretain填写缺少的hour列。

data want;
  merge have
        tmp;
  by id hour;
  retain status_previous;
  if not first.id then do;
    if status ne . then status_previous = status;
    else if status_previous ne . then status = status_previous;
  end;
  if last.id then status_previous = .;
  drop status_previous;
run;

Resulting table 1

以前的解决方案(无id&#39; s)

如果last_hour总是12,那么应该这样做:

data have;
  input hour status last_hour;
  datalines;
2 1 12
4 1 12
5 1 12
6 1 12
7 0 12
9 1 12
10 0 12
;


data hours;
  do i = 0 to 12;
    hour = i;
    last_hour = 12;
    output;
  end;
  drop i;
run;


data want;
  merge have
        hours;
  by hour;
  retain status_previous;
  if status ne . then status_previous = status;
  else if status_previous ne . then status = status_previous;
  drop status_previous;
run;

resulting table 2