【问题标题】:SAS calculation of duration when a variable takes on a specific valueSAS计算变量取特定值时的持续时间
【发布时间】:2016-05-25 08:55:20
【问题描述】:

我有一个数据集,我想在其中计算 SAS 中每个 id 的多个福利法术的持续时间。

开始由变量 y_xxxx 定义,取值为 'welfare',其中前 4 个 y_xxxx 不等于每个 id 的 'welfare'。

End 由变量 y_xxxx 定义,取值为 ‘welfare’,其中后面的 4 个 y_xxxx 不等于 ‘welfare’。如果以下 4 个 y_xxxx 的值为“其他”,则必须删除该咒语而不是整个观察。

持续时间 = end-start+1

每个id可以有多个‘welfare’的拼写,满足以上限制。数据长这样(除了变量y_xxxx在真实数据集中记录到y_1548)。

ID  y_0950   y_0951   y_0952   y_0953   y_1001    y_1002    y_1003   ...  y_1015
01  other    other    other    other    welfare   welfare   welfare  ... 
02  welfare  welfare  welfare  other    other     other     other    ...
03  
04
...
N  other   other     other    other    welfare   welfare   welfare  ...  

我可以计算第一个咒语的持续时间,请参见下面的代码,但如果不一遍又一遍地重复相同的代码,我无法弄清楚如何为每个 id 继续下一个咒语。

%let uger=y_0950--y_1015;
%let welfare='welfare';
%let other='other';

/*Start welfare spell*/
data mydata;
set data;
array y(*) &uger;
do j=5 to 19 until (start);
if  y(j-1) ne &welfare and  
y(j-2) ne &welfare and  
y(j-3) ne &welfare and  
y(j-4) ne &welfare and
y(j) eq &welfare 
then start=j;
end;
if start>0 then output;
run;

/*end welfare spell*/
data mydata1;
set mydata;
array y(*) &uger;
do j=start to 19 until(ends);
if y(j) ne &welfare and
y(j+1) ne &welfare and
y(j+2) ne &welfare and
y(j+3) ne &welfare
then ends=j-1;
end;
/*other*/
do k=start to 19 until(other);
if y(k) eq &other and
y(k+1) eq &other and
y(k+2) eq &other and
y(k+3) eq &other
then other=k-1;
end;
if ends=. then censor=1;
if ends=. then ends=19;
if other >0 then delete;
duration= ends-start+1;
run; 

我希望得到如下数据(与上面的数据示例不对应)

ID  start  end  duration  censor   
01  5      10   6         0         
01  15     19   5         1  
02  6      12   7         0
03  ..
04  ..
04  ..
..
N  

【问题讨论】:

  • Censor 表示最后观察的时期是“福利”?

标签: sas duration


【解决方案1】:

假设censor 表示最后观察的时期是“福利”,这应该可以解决您的问题。

解决这个问题的方法不止一种,但这里的关键是当你在一个值“welfare”之后达到一个值“other”时使用output,并将其他变量重置为缺失(可能是在output 之后也为0),所以你可以重新开始。

要注意的另一件事是向量中最后一个元素的特殊性。在下面的代码中查看我的 cmets。

创建示例数据

data welfare;
  input ID 
        y_0950 $ 
        y_0951 $
        y_0952 $
        y_0953 $
        y_1001 $
        y_1002 $
        y_1003 $;
  datalines;
01 other welfare welfare other other welfare welfare welfare
02 welfare welfare welfare other other other other
03 welfare welfare other other welfare welfare welfare
04 welfare other welfare welfare other welfare other
run;

计算福利期

/* add y_: to the drop if you don't need them */
data welfare_periods (drop=i); 
  format ID start end duration censor 8.;
  set welfare;
  array y(*) y_:;    
  censor = 0;
  start = .;
  end = .;
  duration = .;

  /* Loop over every column y_... */
  do i = 1 to (dim(y)-1);
    if y(i) = "welfare" then do;
      /* Check if we have a new start */
      if duration = . then do;
        start = i;
        end = i; /* We'll increment this later if need be. */
        duration = 1; /* We'll increment this later if need be. */
      end;
      else if y(i-1) = "welfare" then do;
        end = end + 1;
        duration = duration + 1;
      end;
    end;

    /* When y(i) = "other" */
    else if y(i) = "other" then do;
      if duration > 0 then do;
        /* Output the row and reset the start/end/duration variables */
        output;
        start = .;
        end = .;
        duration = .;
      end;
    end;

    /* Decide what to do when we reach last element minus 1 */
    /* We know here that y(i) = "welfare", since the last */
    /* "else if" block took care of y(i)'s equal to "other" */
    if i = dim(y) - 1 and duration > 0 then do;
      if y(i+1) = "welfare" then do;
        end = end + 1;
        duration = duration + 1;
        censor = 1;
        output;
      end;
      else if y(i+1) = "other" then output;
    end;
  end;
run;

结果

【讨论】:

  • 是的,审查员表明最后的观察是福利。谢谢你的回答,对你帮助很大。
  • 不客气,Cornelia,这是一个有趣的问题要解决 :)
猜你喜欢
  • 2014-01-14
  • 2011-07-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-09-24
  • 1970-01-01
相关资源
最近更新 更多