【问题标题】:Summing across SAS arrays based on intervals i.e. start date and end date基于间隔(即开始日期和结束日期)跨 SAS 数组求和
【发布时间】:2020-05-30 15:15:29
【问题描述】:

我正在尝试根据开始日期和结束日期对数组中的变量求和。对于每个 ID,有一行(如果开始和结束日期在同一年内)、两行(如果开始和结束日期在连续年份内)或多行用于不同的开始和结束日期期间。每个月有 12 个变量,即 v1-v12,其中 v1 是一月,v12 是十二月。某些 ID 的两行包含连续 2 年的月度值,即统计年份和结束年份。我正在尝试获取数组变量的总和,但仅从每个 ID 的开始日期到结束日期。例如,对于 ID 1,开始日期是 07/23/2007,结束日期是 06/07/2008,我想从 V7(7 月开始月份)到 2007 年的 v12 和 V1 到 V6(6 月底)的总和2008 年,即第二排。这是我所拥有的:

ID  STARTDATE   ENDDATE      YR    V1  V2  V3  V4  V5  V6  V7  V8  V9  V10 V11 V12
1   07/23/2007  06/07/2008  2007    3   5   2   6   3   2   1   3   4   1   2   3
1   07/23/2007  06/07/2008  2008    0   4   2   2   3   0   1   3   1   0   2   3
2   02/01/2002  07/27/2002  2002    1   0   2   3   1   0   1   2   3   0   0   2
3   05/26/2008  03/07/2009  2008    2   0   2   3   1   2   1   1   3   0   0   1
3   05/26/2008  03/07/2009  2009    4   1   4   3   1   0   2   3   3   1   0   3
3   10/17/2011  08/17/2012  2011    3   3   0   1   0   1   1   5   3   1   0   1
3   10/17/2011  08/17/2012  2012    1   3   2   3   1   0   1   2   3   2   0   2
4   02/27/2004  01/22/2005  2004    2   0   2   3   1   2   1   1   3   0   0   1
4   02/27/2004  01/22/2005  2005    0   4   2   2   3   0   1   3   1   0   2   3

这就是我想要的:

ID  STARTDATE   ENDDATE      YR    V1  V2  V3  V4  V5  V6  V7  V8  V9  V10  V11  V12  sum
1   07/23/2007  06/07/2008  2007    3   5   2   6   3   2  [1   3   4    1    2    3]  25
1   07/23/2007  06/07/2008  2008   [0   4   2   2   3   0]  1   3   1    0    2    3   25
2   02/01/2002  07/27/2002  2002    1  [0   2   3   1   0   1]  2   3    0    0    2    8
3   05/26/2008  03/07/2009  2008    2   0   2   3  [1   2   1   1   3    0    0    1]  18
3   05/26/2008  03/07/2009  2009   [4   1   4]  3   1   0   2   3   3    1    0    3   18
3   10/17/2011  08/17/2012  2011    3   3   0   1   0   1   1   5   3   [1    0    1]  15
3   10/17/2011  08/17/2012  2011   [1   3   2   3   1   0   1   2]  3    2    0    2   15
4   02/27/2004  01/22/2005  2004    2  [0   2   3   1   2   1   1   3    0    0    1]  14
4   02/27/2004  01/22/2005  2005   [0]  4   2   2   3   0   1   3   1    0    2    3   14

这是我尝试过的代码

data want;
  set have;
  array vars(*) V1-V12;
  DT_CHECK=intnx('month',ENDDATE,-12);
  start=intck('month','STARTDATE,DT_CHECK)+1;
  if start<1 then do;
    error 'Start date out of range';
    delete;
    end;
  else if start>dim(vars)-12 then do;
    error 'End date out of range';
    delete;
    end;
  do _N_=start to start+12;
    sum_n+vars(_N_);
    end;
  format DT_CHECK mmddyy10.;
run;

但是我遇到了问题。任何帮助表示赞赏。谢谢你。

【问题讨论】:

  • 你想要什么?只是一个带有 ID 和 SUM 的两个变量数据集以及每个 ID 一个观察值?还是别的什么?
  • 你想要的 ID = 2 看起来很奇怪
  • 嗨,汤姆,我想要 ID,以及其他变量的总和。我相信如果必须的话,我可以将数据集合并回其他变量。但现在得到这笔钱很重要
  • 嗨,理查德,我想要从 2 月到 7 月(0、2、3、1、0、1)的总数为 7。
  • 嗨,理查德,我明白你的意思了,我已经相应地更正了。让我知道现在是否有意义。谢谢。

标签: arrays sas sum intervals


【解决方案1】:

DOW / 串行循环技术可以计算一个组的标准值,然后将该值应用于组中的每一行。

例子:

要求id 中的开始到结束日期间隔是互斥的(即不重叠并且数据按by id startdate enddate 排序)

data want;
  * [sum] variable is implicitly reset to missing at the top of the step.;

  do _n_ = 1 by 1 until (last.enddate);
    set have;
    by id startdate enddate;

    array v(12);

    _month1 = intnx('month', startdate, 0);
    _month2 = intnx('month', enddate,   0);

    do _index = 1 to 12;
      if _month1 <= mdy(_index,1,yr) <= _month2 then sum = sum(sum,v(_index));
    end;
  end;

  do _n_ = 1 to _n_;
    set have;
    output;
  end;

  format sum 4.;
  drop _:;
run;

答案没有解决startdateenddate 间隔在id 内重叠的情况。

【讨论】:

  • 感谢 Richard,数据集不包含任何超出开始日期和结束日期的年份。所以没关系。一个问题是我的 ID 有两个单独的间隔(相同的 ID 号),但我想分别计算每个间隔的总和。再次感谢
  • 啊,我明白了。我将修改代码以在 BY 组中包含日期范围变量,以进一步划分 ID 分组。
【解决方案2】:

由于每个观察代表一年,直接的方法是从一月到十二月循环一个月,并检查该月是否在您的日期范围内。

data want;
 do until(last.startdate);
   set have;
   by id startdate;
   array v v1-v12;
   do month=1 to 12 ;
     if intnx('month',startdate,0,'b')<=mdy(month,1,yr)<=intnx('month',enddate,0,'e')
       then sum=sum(sum,v[month])
     ;
   end;
 end;
 keep id startdate enddate sum;
run;

结果:

Obs    ID     STARTDATE       ENDDATE    sum

 1     1     2007-07-23    2008-06-07     25
 2     2     2002-02-01    2002-07-27      7
 3     3     2008-05-26    2009-03-07     18
 4     3     2011-10-17    2012-08-17     15
 5     4     2004-02-27    2005-01-22     14

【讨论】:

  • 谢谢汤姆,问题是我需要将 ID 3 分成 2 个时间段,即05/26/2008 至 03/07/2009 和 10/17/2011 至 08/17/2012。同样对于 ID 2 这样的 id 3 有两行,第一行总和为 18,第二行总和为 15。再次感谢
  • 更改 BY 组。 first.startdate ... by id startdate;
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-19
  • 1970-01-01
  • 2012-10-25
  • 2016-08-21
相关资源
最近更新 更多