2016-08-11 3 views
0

Я работаю над созданием макроса слияния хешей, и я хочу создать набор данных для объединенной таблицы и наборов данных для отсутствующих значений. Вот пример того, что я ищу с регулярным слиянием.SAS Hash Merge Macro - вывод нескольких наборов данных

data &onto miss&varnm xtra&varnm; 
    merge &onto(in=in1) fr2(in=in2); 
    by &byvars; 
    if in2 then from = "&from"; 
    else from = "&onto"; 
    if in1 and in2 then output &onto; 
    else if in1 and not in2 then output &onto miss&varnm; 
    else if not in1 and in2 then output xtra&varnm; 
run; 

Я думаю, что у меня есть слияние работает довольно хорошо, но я не уверен, как идти о получении «отсутствует» наборы данных, так что любая помощь будет оценена.

%macro hashmerge(varnm,onto,from,byvars); 
/* The inputs are the variables to merge, 
    the merge onto data set, the merge from 
    data set and the key(s). vanrnm and 
    byvars are set up to accept multiple inputs. */ 

%let data_vars = %trim (&varnm); 
%let data_vars_a = %sysfunc(tranwrd(&data_vars.,%str(),%str(","))); 
%let data_vars_b = %sysfunc(tranwrd(&data_vars.,%str(), %str(,))); 
%let data_key = %trim (&byvars); 
%let data_key = %sysfunc(tranwrd(&data_key.,%str(), %str(","))); 

data &onto(drop=rc); 
set &onto &from(keep=&varnm &byvars); 

declare hash h_merge (dataset: "&from."); 

rc = h_merge.DefineKey ("&data_key."); 
rc = h_merge.DefineData ("&data_vars_a."); 
rc = h_merge.DefineDone(); 

do until (eof); 
    set &onto end = eof; 
    call missing(&data_vars_b.); 
    rc = h_merge.find(); 
    output; 
end; 
stop; 
run; 

%mend; 
+0

Вы используете это только для взаимного объединения? – Quentin

+0

Нет, я буду использовать это для разных слияний. –

ответ

0

С тем, как вы настроили свой хэш-объект, который вы не можете легко получить xtra набор данных. Вы будете в состоянии получить miss и onto из них не слишком много потрудился через что-то вроде этого, плюс необходимые изменения в свой data заявление:

if rc = 0 then output &onto; 
else output miss&varnm; 

Однако, чтобы найти все значения в вашем from наборе данных, которые вам еще не использовали, которые обычно попадают в набор данных xtra, вам нужно будет отслеживать, какие значения у вас имеют, используемые при слиянии, а затем в конце шага данных копируйте остальные в новый хеш объект и вывод этого объекта.

N.B. с вашим текущим кодом все строки выводятся в набор данных &onto, даже если у них отсутствуют значения для ваших переменных поиска.

0

Это немного сложно сделать, но здесь у вас есть образец идеи, как это можно сделать.

Создайте еще один хэш-объект хэша, как и первый. Из второго объекта вы удалите элементы allready. В конце вы просто выводите второй объект в набор данных. Требуется память для хэш-объектов, но первая попытка.

(Не запускать код и извините за ошибки)

%macro hashmerge(varnm,onto,from,byvars); 
/* The inputs are the variables to merge, 
    the merge onto data set, the merge from 
    data set and the key(s). vanrnm and 
    byvars are set up to accept multiple inputs. */ 

%let data_vars = %trim (&varnm); 
%let data_vars_a = %sysfunc(tranwrd(&data_vars.,%str(),%str(","))); 
%let data_vars_b = %sysfunc(tranwrd(&data_vars.,%str(), %str(,))); 
%let data_key = %trim (&byvars); 
%let data_key = %sysfunc(tranwrd(&data_key.,%str(), %str(","))); 

data &onto (drop=rc); 
    if 0 set &onto &from(keep=&varnm. &byvars.); 

    declare hash h_merge (dataset: "&from."); 
    rc = h_merge.DefineKey ("&data_key."); 
    rc = h_merge.DefineData ("&data_vars_a."); 
    rc = h_merge.DefineDone(); 

    /*hash table that will hold data not yet founded by find method */ 
    declare hash h_merge_copy (dataset: "&from."); 
    rc = h_merge_copy.DefineKey ("&data_key."); 
    rc = h_merge_copy.DefineData ("&data_vars_a."); 
    rc = h_merge_copy.DefineDone(); 

    do until (eof); 

     set &onto. end = eof; 

     if h_merge.find() = 0 then do; 
     /*removing data from h_merge_copy if founded and if not allready removed*/ 
     if h_merge_copy.check() = 0 then do; 
      rc = h_merge_copy.remove(); 
     end; 
     end; 
     else 
     output miss&varnm.; /*no find match - output to miss&varnm.*/ 

     output &onto.; /*find match in hash or not output to &onto. (left join)*/ 
    end; 

    h_merge_copy.output(dataset: "&onto."); 

    stop; 
run; 

%mend; 

я могу улучшить это потреблять чуть меньше памяти, как не хранящих данные во второй хэш, но сегодня это Allready слишком поздно. Надеюсь, это немного помогло.

+0

Если это слияние одного к одному, не может ли этот подход работать только с одной хеш-таблицей? Если Find() успешно, вы можете удалить(), поскольку вам нужно только один раз прочитать каждую запись. – Quentin

+0

@Quentin Вы правы, но я сделал более общий подход. Если one2one, то это может быть один хеш. – fl0r3k

+0

Итак, с таким подходом вы могли бы дублировать значения в & on, но не могли обрабатывать дубликаты по значениям в & from, правильно? – Quentin

0

Спасибо за помощь и предложения каждого. Я не был уверен, как добавить набор данных «xtra», не создавая другого хэша, который побеждает цель слияния хешей. Итак, вот что мне нужно для создания отсутствующего и объединенного набора данных.

%macro hashmerge(varnm,onto,from,byvars); 


%let data_vars = %trim (&varnm); 
%let data_vars_a = %sysfunc(tranwrd(&data_vars.,%str(),%str(","))); 
%let data_vars_b = %sysfunc(tranwrd(&data_vars.,%str(), %str(,))); 
%let data_key = %trim (&byvars); 
%let data_key = %sysfunc(tranwrd(&data_key.,%str(), %str(","))); 

data &onto(drop=rc) miss&varnm(drop=rc); 
    if 0 then set &onto &from(keep=&varnm. &byvars.); 

    declare hash h_merge (dataset: "&from."); 
    rc = h_merge.DefineKey ("&data_key."); 
    rc = h_merge.DefineData ("&data_vars_a."); 
    rc = h_merge.DefineDone(); 

    do until (eof); 
    set &onto end = eof; 
    call missing(&data_vars_b.); 
    rc = h_merge.find(); 
    if rc = 0 then do; 
     output &onto; 
     from = "&from."; 
    end; 
    else do; 
     output miss&varnm &onto; 
     from = "&onto."; 
    end; 
    end; 

stop; 
run; 

%mend; 

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

Пожалуйста, разместите предложение, если кто-нибудь знает более эффективный способ сделать это.

Смежные вопросы