SAS: Отметка следующих и предыдущих наблюдений как конфликты

Я хочу создавать манекены в SAS. Мой план таков: каждый раз AnnouncementDate ne. Я хочу создать переменную с именем event = 2 и следующую также (event = 2), а также пять предыдущих наблюдений 1 И все это помечено, если предыдущие 5 наблюдений и день после даты объявления не пусты. и по классам (например, по акциям)

выходные данные

date announcementdate event conflict
1115 . . .
2115 . . .
3115 . . .
4115 . . .
5115 . . .
6115 . 1 .
7115 . 1 .
8115 . 1 .
9115 . 1 .
10115 . 1 .
11115 1115 2 .
12115 . 2 .
13115 . .
14115 . 1 .
16115 . 1 .
17115 . 1 .
18115 . 1 .
19115 . 1 .
20115 20115 2 
21115 . 1 Y
21115 . 1 Y
22115 22115 2 Y
23115 . 2 Y
24115 . .
25115 . .

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

Мой текущий код является ведущим термином, поскольку я объединяю только столбец событий с firstobs = 2. В любом случае, это отставание в 5 раз беспокоит меня, а также конфликт, связанный с предыдущими наблюдениями.

data want1 ; set have;;
if announcementdate ne . then event=0;
run;

data want2; merge want1 (firstobs=2) want1 (keep=event rename= (event=event2)); 
if event2=0 then event=0; 
if event2=0 then event=event2;
run;

Спасибо за любой вклад!


person MaBo88    schedule 20.04.2017    source источник


Ответы (1)


Мой подход к этому состоит в том, чтобы сначала проанализировать набор данных, чтобы определить, какими будут диапазоны, используя _n_ в качестве индикатора (а не идентификатора). Затем вы можете построить простой начальный и конечный диапазон и использовать его для построения формата (ну, два, один для 1 и один для 2).

Затем проанализируйте этот набор данных с помощью упреждающего слияния (чтобы получить следующее значение start) и посмотрите, существует ли конфликт; затем используйте свою логику, чтобы определить другой формат маркеров конфликта. В моем примере есть логика для этого; он может или не может соответствовать вашим точным потребностям, поэтому вам, возможно, придется немного подумать об этой логике и изменить ее, поскольку она довольно специфична.

Затем вы просто применяете формат, используя _n_ в качестве входных данных. Конечно, убедитесь, что исходный набор данных не отсортирован.

Вот полный код.

data have;
input date announcementdate event_want conflict_want $;
datalines;
1115 . . .
2115 . . .
3115 . . .
4115 . . .
5115 . . .
6115 . 1 .
7115 . 1 .
8115 . 1 .
9115 . 1 .
10115 . 1 .
11115 1115 2 .
12115 . 2 .
13115 . . .
14115 . 1 .
16115 . 1 .
17115 . 1 .
18115 . 1 .
19115 . 1 .
20115 20115 2 .
21115 . 1 Y
21115 . 1 Y
22115 22115 2 Y
23115 . 2 Y
24115 . . .
25115 . . .
;;;;
run;

data for_fmt;
  set have nobs=nobs;
  length fmtname $16;
  fmtname = 'eventf';

  if _n_=1 then do;   *HLO='o' gives the 'other' value;
    start=.;
    end  =.;
    label = ' ';
    hlo='o';
    output;
  end;
  hlo=' ';

  if not missing(announcementdate) then do;
    start = max(1,_n_-5);
    end   = max(1,_n_-1);
    label='1';
    output;
    start = _n_;
    end   = min(_n_+1,nobs);
    label='2';
    output;
  end;
run;  *now we have a dataset of the ranges - but they overlap;

data for_fmt_conflicts;

  merge for_fmt(in=a) for_fmt(in=_in_next firstobs=2 keep=start rename=start=next_start); *look-ahead merge;
  retain new_start conflict_marker;
  if hlo='o' then do;    *again the 'other' row;
    output;
    fmtname='conflictf';
    output;
  end;
  else if end gt next_start and (_in_next) then do;   *if the next row will be a conflict, adjust the end back one and indicate where next should start;
    end = end-1;
    new_start = end+1;
    conflict_marker=1;
    output;
  end;
  else if conflict_marker=1 then do;  *if this is a conflict row type 1;
    start = new_start;
    output;
    fmtname='conflictf';
    label  ='Y';
    output;
    conflict_marker=2;
  end;
  else if conflict_marker=2 then do;  *if this is the 2s for a conflict row;
    output;
    fmtname='conflictf';
    label  ='Y';
    output;
    conflict_marker=0;
  end;
  else output;
run;
proc sort data=for_fmt_conflicts;  *must sort to get fmtnames grouped together;
  by fmtname start;
run;
proc format cntlin=for_fmt_conflicts;  *import formats;
quit;

data want;  *now apply formats;
  set have;
  event = put(_n_,eventf.);
  conflict = put(_n_,conflictf.);
run;
person Joe    schedule 20.04.2017
comment
Огромное спасибо! Немного подправили, но это фантастика !! - person MaBo88; 21.04.2017
comment
Что ж, есть кое-что. Я могу делать все, что захочу, но это продолжает выдавать мне ошибку: начало больше, чем конец. - person MaBo88; 21.04.2017