Разделить набор данных, если значение переменной появляется дважды - PullRequest
0 голосов
/ 05 сентября 2018

Я хочу разбить набор данных на два подмножества. Я хочу, чтобы первое подмножество включало все строки, в которых значения id или id1 появляются более одного раза.

Как и для этого,

data test;
input id id1 var1 $ var2 $;
datalines;
1 11 A B
2 22 C D
3 11 E F
3 12 G H
7 15 K L
3 13 M N
2 10 I J
8 16 P L
;;;;
run;

Я хочу, чтобы подмножества были

1 11 A B
2 22 C D
3 11 E F
3 12 G H
3 13 M N
2 10 I J

и

7 15 K L
8 16 P L

Я могу использовать приведенный ниже код, но он неэффективен, поскольку при разбиении существует два прохода через набор данных. Любые другие варианты?

proc sql;
create table DuplicateId as
select id from test
group by id
having count(id) > 1;
quit;

proc sql;
create table DuplicateID1 as 
select id1 from test
group by id1
having count(id1) > 1;
quit;

proc sql;
create table split1 as 
select * from test 
where id not in (select id from DuplicateID) and id1 not in (select id1 from DuplicateID1);
quit;

proc sql;
create table split2 as
select * from test
where id in (select id from DuplicateID) or id1 in (select id1 from DuplicateID1);
quit;

Ответы [ 2 ]

0 голосов
/ 05 сентября 2018

Я думал, что представление может работать, но оно определенно больше проходов и определенно более неэффективно. Петля DoW, вероятно, является лучшим решением, по крайней мере, только два прохода, этот, вероятно, минимум 4 прохода! Строковые запросы определенно менее эффективны.

Интересная проблема, хотя. Может также помочь, если вы объясните какой-то контекст, возможно, есть более простой способ решить эту проблему?

proc sql;
    create view test2 as select *, (select count(_a1.ID) from test as _a1 where 
        _a1.id=t1.id group by id) as count1, (select count(_a2.ID1) from test as _a2 
        where _a2.id1=t1.id1 group by id1) as count2 from test as t1 order by 1, 2;
quit;

data single multiple;
    set test2;

    if max(count1, count2)>1 then
        output multiple;
    else
        output single;
run;
0 голосов
/ 05 сентября 2018

Ваш код делает 4 прохода через данные. По одному для поиска уникальных (или дублирующих) кодов для каждой отдельной переменной ID. И по одному на каждый выходной набор данных. Вы можете уменьшить этот последний шаг до одного прохода, используя индексированный поиск.

proc sql ;
create table dup1 (index=(id)) as
  select id from test
  group by 1 having count(*) > 1
;
create table dup2 (index=(id1)) as
  select id1 from test
  group by 1 having count(*) > 1
;
quit;
data single multiple;
  set test;
  set dup1 key=id / unique;
  if _iorc_ then set dup2 key=id1 / unique;
  if _iorc_ then output single;
  else output multiple;
  _error_=0;
run;

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

Затем вы можете записать их обратно и использовать шаг данных выше для разделения. Или просто сделайте шаг, который создает объекты хеша, перечитайте набор данных снова.

...