Общая проблема назначения идентификатора группы на основе связей между строками может быть очень сложной и сложной.Однако для последовательного случая решение не так уж плохо.
Пример кода
Предполагается, что идентичность группы изменяется, когда оба значения переменных отсутствуют в предыдущей строке.
data have;input
Var1 $ Var2 $;datalines;
A B
B C
C D
D E
F G
H F
run;
data want;
set have;
group_id + ( var1 ne lag(var2) AND var2 ne lag(var1) );
run;
Сложный случай
@ Состояния Вивека Гупты в комментариях
В наборе данных есть случайное расположение строк
Рассмотрим произвольные строки p и q с элементами X и Y. Группы создаются по связям, критерии которых:
p.X = q.X
OR p.X = q.Y
OR p.y = q.x
OR p.y = q.y
Решатель на основе хеш-функции первоначально заполняет группы из сканирования данных.Повторное сканирование данных с поиском по хэшу переносит элементы в более низкие группы (увеличивая таким образом группу), пока не будет выполнено сканирование без миграций.
data pairs;
id + 1;
input item1 $ item2 $ ;
cards;
A B
C D
D E
B C
H F
X Y
F G
run;
data _null_ ;
length item $8 group 8;
retain item '' group .;
if 0 then set pairs;
declare hash pairs();
pairs.defineKey('item1', 'item2');
pairs.defineDone();
declare hash map(ordered:'A');
map.definekey ('item');
map.definedata ('item', 'group');
map.definedone();
_groupId = 0;
noMappings = 0;
nPass = 0;
do until (end);
set pairs end=end;
pairs.replace();
found1 = map.find(key:item1) eq 0; item1g = group;
found2 = map.find(key:item2) eq 0; item2g = group;
put item1= item2= found1= found2= item1g= item2=;
select;
when ( found1 and not found2) map.add(key:item2,data:item2,data:item1g);
when (not found1 and found2) map.add(key:item1,data:item1,data:item2g);
when (not found1 and not found2) do;
_groupId + 1;
map.add(key:item1,data:item1,data:_groupId);
map.add(key:item2,data:item2,data:_groupId);
end;
otherwise
;
end;
end;
declare hiter data('pairs');
do iteration = 1 to 1000 until (discrete);
put iteration=;
discrete = 1;
do index = 1 by 1 while (data.next() = 0);
found1 = map.find(key:item1) eq 0; item1g = group;
found2 = map.find(key:item2) eq 0; item2g = group;
put index= item1= item2= item1g= item2g=;
if (item1g < item2g) then do; map.replace(key:item2,data:item2,data:item1g); discrete=0; end;
if (item2g < item1g) then do; map.replace(key:item1,data:item1,data:item2g); discrete=0; end;
end;
end;
if discrete then put 'NOTE: discrete groups at' iteration=; else put 'NOTE: Groups not discrete after ' iteration=;
map.output(dataset:'map');
run;
Сложный случай # 2
Группы создаются по ссылкам, критерии которых
p.X = q.X
OR p.y = q.y
Следующий пример является внешним и слишком длинным для публикации здесь.
Как создавать группы из строк, связанных ссылками влюбая из двух переменных
Общая формулировка задачи:
Given: P = p{i} = (p{i,1),p{i,2}), a set of pairs (key1, key2).
Find: The distinct groups, G = g{x}, of P,
such that each pair p in a group g has this property:
key1 matches key1 of any other pair in g.
-or-
key2 matches key2 of any other pair in g.
Вкратце, пример показывает
- Итеративныйспособ использования хэшей.
- Два хэша поддерживают идентификатор группы, назначенный каждому значению ключа.
- Два дополнительных хэша используются для поддержки путей отображения группы.
- Когда данные могут быть переданыне вызывая сопоставление, тогда группы были полностью определены.
- Окончательный проход сделан
- groupIds назначены каждой паре
- данные выводятся в таблицу