У меня есть список имен, телефонных номеров и адресов с ~ 5 000 000 строк. Я пытаюсь создать список уникальных клиентов по каждому адресу, каждому из которых назначается ключ. Имена клиентов не отформатированы согласованно, поэтому Джон Смит может выглядеть как, например, Смит, Джон или Джон Смит-младший и т. Д.
Логика, которой я хочу следовать, такова:
Если две записи по адресу имеют один и тот же номер телефона, это один и тот же клиент, независимо от того, имеют ли они разные имена или нет, и ему назначается один и тот же ключ customer_
Если две записи по адресу не имеют одного и того же номера телефона (или не имеют номера телефона), но нечеткое совпадение их имен превышает некоторый порог, они являются одним и тем же клиентом, и им присваивается тот же ключ customer_ *. 1011 *
Обратите внимание, что одно и то же имя клиента + номер телефона должны совпадать на двух разных адресах, и не должен быть присвоен один и тот же ключ клиента.
Вот примеры таблиц, содержащих примеры ввода и желаемого результата:
https://docs.google.com/spreadsheets/d/1RsABSFy5a5dLE8mC-ZQF_lNg4I0kLQy7dEFhbfovq40/edit?usp=sharing
Моя попытка кода с использованием этого примера набора данных приведена ниже:
data customer_keys(keep=customer_name customer_key customer_phone clean_address);
length customer_name $50 Comp_Name $20 customer_key 8 clean_address comp_address $5 customer_phone comp_phone $11.;
if _N_ = 1 then do;
declare hash h(multidata:'Y');
h.defineKey('Comp_Name','comp_address');
h.defineData('Comp_Name', 'customer_key','comp_address', 'comp_phone');
h.defineDone();
declare hiter hi('h');
declare hash hh(multidata:'Y');
hh.defineKey('customer_key');
hh.defineData('customer_key', 'Comp_Name','comp_address','comp_phone');
hh.defineDone();
_customer_key=0;
end;
set testdat;
rc=h.find(key:customer_name, key:clean_address);
if rc ne 0 then do;
rc=hi.first();
do while (rc=0);
if not missing(customer_phone) and clean_address=comp_address and customer_phone=comp_phone
then do;
h.add(key:customer_name,key:clean_address, data:customer_name, data:customer_key, data:clean_address, data:customer_phone);
hh.add();
end;
else if not missing(customer_name) and clean_address=comp_address and jaroT(customer_name,Comp_name) ge 0.8
then do;
rc=hh.find();
do while (r ne 0);
dist2=jaroT(customer_name,Comp_name);
hh.has_next(result:r);
if r=0 & dist2 ge 0.8 then do;
h.add(key:customer_name,key:clean_address, data:customer_name, data:customer_key, data:clean_address, data:customer_phone);
hh.add();
output;return;
end;
else if r ne 0 & dist2 ge 0.8
then rc=hh.find_next();
else if dist2 < 0.8
then leave;
end;
end;
rc=hi.next();
end;
_customer_key+1;
customer_key=_customer_key;
h.add(key:customer_name,key:clean_address, data:customer_name, data:customer_key, data:clean_address, data:customer_phone);
hh.add(key:customer_key, data:customer_key, data:customer_name, data:clean_address, data:customer_phone);
end;
output;
run;
Запуск этого кода приводит к ошибке:
ERROR: Hash object added 23068656 items when memory failure occurred.
FATAL: Insufficient memory to execute DATA step program. Aborted during the EXECUTION phase.
ERROR: The SAS System stopped processing this step because of insufficient memory.
Я замечаючто еслиЯ полностью удаляю дополнительную логику, связанную с номером телефона, у меня нет этой проблемы с памятью. Однако я все еще собираюсь предположить, что мой подход потерпит неудачу в любом случае из-за нехватки памяти, когда я попытаюсь запустить его на полном наборе данных.