SAS удаляет дубликаты путем повторного появления фрагментов записей

У меня есть набор данных с повторным появлением фрагментов данных в группах наблюдений одинаковой длины, таких как:

    data have;
    input name $    identifier ;
    cards;
    mary     1
    mary     2
    mary     2
    mary     4
    mary     5
    mary     7
    mary     6
    adam     2
    adam     3
    adam     3
    adam     7
    /*remove*/
    mary     1
    mary     2
    mary     2
    mary     4
    mary     5
    mary     7
    mary     6
    /*remove*/
    adam     8
    mary     1
    mary     2
    mary     3
    mary     4
    mary     5
    mary     7
    mary     6
    adam    9
    mary     1
    mary     2
    mary     3

    ;

Я надеюсь удалить фрагмент повторного появления Мэри, отмеченный /remove/ с упорядоченным идентификатором. Результат должен быть примерно следующим:

mary     1
mary     2
mary     4
mary     5
mary     6
mary     7
adam    2 
adam    3 
adam    7
adam    8
mary     1
mary     2
mary     3
mary     4
mary     5
mary     6
mary     7
adam     9
mary     1
mary     2
mary     3

Спасибо за любую помощь! Кто-то подсказал метод по Hash table, но я подозреваю, что у меня может не хватить памяти для обработки кода. Можно ли это сделать с помощью datasteps или proc sql?


person lydias    schedule 07.11.2019    source источник


Ответы (1)


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

data want ;
do until (last.name);
  set have ;
  by name notsorted ;
  length taglist $200 ;
  taglist=catx('|',taglist,identifier);
end;
if _n_=1 then do;
  dcl hash h();
  h.defineKey('name','taglist');
  h.defineDone();
end;
found = 0 ne h.add();
do until (last.name);
  set have ;
  by name notsorted ;
  if not found then output;
end;
drop found taglist;
run;

Если ключи слишком велики, чтобы поместиться в хэш-объект, вам потребуется выполнить несколько проходов. Сначала найдите группы. Затем найдите первое вхождение каждого типа группы. Затем сгенерируйте данные для этих групп.

data pass1 ;
  group + 1;
  first_obs=row+1;
  do until (last.name);
    set have ;
    by name notsorted ;
    length taglist $200 ;
    taglist=catx('|',taglist,identifier);
    row+1;
  end;
  last_obs=row;
  output;
  keep group name taglist first_obs last_obs;
run;

proc sql ;
  create table pass2 as
    select group,first_obs,last_obs
    from pass1
    group by name,taglist
    having min(group)=group
    order by group
  ;
quit;

data want;
  set pass2;
  do obs=first_obs to last_obs;
    set have point=obs;
    output;
  end;
  drop /*group*/ first_obs last_obs ;
run;

Результат:

Obs    group    name    identifier

  1      1      mary         1
  2      1      mary         2
  3      1      mary         2
  4      1      mary         4
  5      1      mary         5
  6      1      mary         7
  7      1      mary         6
  8      2      adam         2
  9      2      adam         3
 10      2      adam         3
 11      2      adam         7
 12      4      adam         8
 13      5      mary         1
 14      5      mary         2
 15      5      mary         3
 16      5      mary         4
 17      5      mary         5
 18      5      mary         7
 19      5      mary         6
 20      6      adam         9
 21      7      mary         1
 22      7      mary         2
 23      7      mary         3
person Tom    schedule 07.11.2019
comment
Размер набора данных составляет около 800 миллионов байт. Памяти для хэша обычно не хватает. - person lydias; 07.11.2019
comment
Является ли набор данных только этими двумя переменными? Возможно, вы могли бы сделать это без хэша, но реальный вопрос: можно ли на самом деле создать переменную TAGLIST? Какова максимальная длина любой группы? Поместится ли список идентификаторов в одну символьную переменную? SAS имеет ограничение в 32 КБ на символьную переменную. - person Tom; 08.11.2019
comment
Я не знаю максимальную длину группы, так как данные будут импортироваться ежедневно, а анализ будет выполняться в режиме реального времени. Длина будет очень длинной, до 300+ элементов, потому что это онлайн-данные журнала пользователей. Идентификатор будет иметь разную длину, поскольку некоторые из них будут метками времени. Звучит ужасно, но это реальность, с которой я имею дело. - person lydias; 08.11.2019