Как подсчитать количество дней, когда у ID положительный и отрицательный баланс в SAS - PullRequest
0 голосов
/ 16 октября 2018

Мои данные следующие:

id   balance  date
1     10      02Mar2018
1     12      05Mar2018
1    -15      07Mar2018
1     14      14Mar2018
1    -25      25Mar2018

Теперь я хочу, чтобы число дней, в течение которых идентификатор 1 был положительным, и число дней, когда идентификатор был отрицательным, в месяце марта.Например, число дней с положительным значением будет рассчитываться следующим образом: с 01 марта по 06 марта, поскольку первая отрицательная запись поступила 07 марта, то есть 6 дней.Затем он снова пошел на положительное сальдо с 14 по 24, то есть за 11 дней, так что в целом это было 6 + 11 = 17 дней с положительным результатом.

И аналогично для отрицательного сальдо.

Я пытался использоватьследующий код:

DATA B;
SET A ;
BY ID;
IF FIRST.ID THEN Y=DATE;
RETAIN Y;
ELSE Y=INTCK('day',DATE,Y);
RUN;

Но не удалось получить точные результаты.Любая помощь будет оценена.

1 Ответ

0 голосов
/ 16 октября 2018

Предполагается, что ваши данные отсортированы по id и date.

Сначала сделайте слияние на будущее (чтобы получить следующую дату):

data lookahead ;
  merge have
        have (firstobs=2 rename=(date=nextdate id=nextid)) ;

  if id ^= nextid then call missing(nextdate) ;
  drop nextid ;
run ;

/* data now looks like this */
id   balance  date      nextdate
1     10      02Mar2018 05Mar2018
1     12      05Mar2018 07Mar2018
1    -15      07Mar2018 14Mar2018
1     14      14Mar2018 25Mar2018
1    -25      25Mar2018

ЗатемРазверните отсутствующие даты, рассматривая случаи, когда первая дата для идентификатора не является первой в месяце, а последняя запись для идентификатора не является последним днем ​​месяца:

data expand ;
  set lookahead (rename=(date=thisdate)) ;
  by id ;

  if first.id and day(thisdate) ^= 1 then do ;
    /* loop from 1st of month to day before date, output new record for each date */
    do date = intnx('month',thisdate,0,'b') to thisdate - 1 ;
      output ;
    end ;
  end ;

  /* output the input record */
  date = thisdate ; output ;

  /* output dates up to the next date */
  if nextdate > thisdate + 1 then do ;
    do date = thisdate + 1 to nextdate - 1 ;
      output ;
    end ;
  end ;
  else 
  /* last record for id, loop to end of month */
  if missing(nextdate) and thisdate ^= intnx('month',thisdate,0,'end') then do ;
    do date = thisdate + 1 to intnx('month',thisdate,0,'end') ;
      output ;
    end ;
  end ;

  drop thisdate nextdate ;
  format date date9. ;
run ;

/* data now looks like this */
id   balance  date      
1     10      01Mar2018
1     10      02Mar2018
1     10      03Mar2018
1     10      04Mar2018 
1     12      05Mar2018
1     12      06Mar2018 
1    -15      07Mar2018
1    -15      08Mar2018
... etc ...
1    -15      13Mar2018 
1     14      14Mar2018
1     14      15Mar2018
... etc ... 
1     14      24Mar2018
1    -25      25Mar2018
... etc ...
1    -25      31Mar2018

Теперь должно быть относительно легко помечать значения соответствующим образом и подсчитывать их по идентификатору / месяцу.

...