SAS-идентификация трех предыдущих лет - PullRequest
0 голосов
/ 02 февраля 2020

Я использую следующий код для идентификации и вывода трех предыдущих лет. Чтобы получить более подробную информацию, образец включает несколько идентификаторов людей, и каждый идентификатор человека имеет наблюдения в течение нескольких лет. В окончательной выборке будет сохранено только удостоверение личности человека, которое, по крайней мере, имело три предыдущих года (например, 2001, 2002, 2003).

data have3 ;
  set have2;
  by personid;
  set have2 ( firstobs = 2 keep = year rename = (year = _year2) )

      have2 (      obs = 1 drop = _all_                        );

  _year2 = ifn(  last.personid, (.), _year2 ); /*output the value of next year*/

  set have2 ( firstobs = 3 keep = year rename = (year = _year3) )

      have2 (      obs = 2 drop = _all_                        );

  _year3 = ifn(  last.personid, (.), _year3 );  /*output the value of the year after the next year*/

  _prev1 = ifn( first.personid, (.), lag(year) ); /*output the value of previous year*/

  _prev2 = ifn( first.personid, (.), lag2(year) );/*output the value of the year before the previous year*/


  if (year-2 eq _prev1-1 eq _prev2) or

     (year+2 eq _year2+1 eq _year3) or

     (year eq _year2-1 eq _prev1+1) then output;

run;

Этот код подходит в большинстве случаев. Тем не менее, мой образец имеет несколько хитрых ситуаций. На следующем рисунке показана одна из ситуаций. У человека с ID 488 есть только два наблюдения (1994 и 1995 годы). К сожалению, первый год следующего идентификатора человека 489 - 1996. Следовательно, _year3 из ID488 Year1994 - это 1996, что делает year+2 eq _year2+1 eq _year3 реальностью. В результате ID488 Year1994 также выводится в окончательный образец. Как я могу улучшить код, чтобы избежать этой ситуации? Спасибо!

enter image description here

Ответы [ 2 ]

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

Вероятно, будет проще просто сохранить переменную id в ваших инструкциях SET.

set have2(firstobs=2 keep=personid year rename=(personid=personid2 year=_year2))...
set have2(firstobs=3 keep=personid year rename=(personid=personid3 year=_year3))...

Затем вы можете убедиться, что следующая и следующая-следующие записи действительно предназначены для тот же PERSONID.

if personid ne personid2 then _year2=.;
if personid ne personid3 then _year3=.;

То же самое для переменных вашего просмотра.

_prev1=lag(year);
_prev2=lag2(year);
if personid ne lag(personid) then _prev1=.;
if personid ne lag2(personid) then _prev2=.;
0 голосов
/ 02 февраля 2020

A SQL запрос может быть более понятным:

%* group has at least 3 years;
create table want as
select *
from have
group by id
having count(distinct year) >= 3

A DOW l oop может вычислить переменную состояния, которая указывает, что группа провела 3 года где-то в пределах

%* group has a run of 3 years somewhere in time;
data want;
  do _n_ = 1 by 1 until (last.id);
    set have;
    by id;
    if _n_ >= 3 and lag2(year)+1 = lag(year) and lag(year)+1 = year then 
      _group_has_3_consective_years = 1;
  end;

  do _n_ = 1 to _n_;
    set have;
    if _group_has_3_consective_years then OUTPUT;
  end;

  drop _:;
run;

DOW l oop также может вычислять переменные состояния для более сложного случая получения данных от групп, чей цикл составляет 3 года и заканчивается в последний год группы.

%* group has a run of 3 years finishing at end time;
data want_3_ending;
  do _n_ = 1 by 1 until (last.id);
    set have;
    by id;
    if _n_ >= 3 and lag2(year)+1 = lag(year) and lag(year)+1 = year then do;
      _group_has_3_consective_years = 1;
      _end_at_year = year;
    end;
  end;

  _top_year = year;

  do _n_ = 1 to _n_;
    set have;
    if _group_has_3_consective_years and _end_at_year = _top_year then OUTPUT;
  end;

  drop _:;
run;

ПРИМЕЧАНИЕ. Вызовы LAG всегда разрешаются, потому что операторы SAS if выполняют NOT выполнение анализа ярлыка c. _N_ >= 3 гарантирует, что все лаги относятся к одной группе.

...