Суммирование по массивам SAS на основе интервалов, то есть даты начала и окончания - PullRequest
0 голосов
/ 14 февраля 2020

Я пытаюсь суммировать переменные в массиве на основе начальной и конечной даты. Для каждого идентификатора имеется одна строка (если даты начала и окончания находятся в одном и том же году), две строки (если даты начала и окончания находятся в пределах последовательных лет) или несколько строк для разных периодов дат начала и окончания. Есть 12 переменных с количеством для каждого месяца, т.е. v1-v12, где v1 - январь, а v12 - декабрь. Две строки для некоторого идентификатора содержат месячные значения для двух последовательных лет, то есть в течение года статистики и года окончания. Я пытаюсь получить сумму счета для переменных массива, но только от начальной даты до конечной даты для каждого идентификатора. Например, для идентификатора 1 начальная дата - 23.07.2007, а конечная - 07.07.2008, я хотел бы суммировать значения от V7 (месяц начала июля) до v12 в 2007 году и от V1 до V6 (месяц окончания июня) в 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;

Но у меня проблемы. Любая помощь приветствуется. Спасибо.

Ответы [ 2 ]

1 голос
/ 14 февраля 2020

Поскольку каждое наблюдение представляет один год, прямой подход будет состоять в том, чтобы всего лишь 1 oop месяц с января по де c и проверить, попадает ли этот месяц в диапазон дат.

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
1 голос
/ 14 февраля 2020

Метод DOW / serial l oop может вычислить значение для критериев по группе, а затем применить это значение к каждой строке в группе.

Пример:

Требуется запуск чтобы интервалы дат в пределах 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;

Ответ не относится к сценарию интервалов от startdate до enddate которые перекрываются в пределах id.

...