2016-08-11 40 views
0

ハッシュマージマクロを作成中です。マージされたテーブルのデータセットと欠損値のデータセットを作成したいと思います。ここで私が定期的なマージで探しているものの例です。SASハッシュマージマクロ - 複数のデータセットを出力する

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; 

私はかなりよく実行されているマージを持っていると思いますが、私は任意の助けをいただければ幸いですので、「欠けている」データセットを得ることについて行くするかどうかはわかりません。あなたは簡単にxtraデータセットを取得することはできませんあなたのハッシュオブジェクトを設定した方法で

%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

これは1対1マージでのみ使用していますか? – Quentin

+0

いいえ、私は別のマージのためにこれを使用します。 –

答えて

0

。もしあなたfromデータセット内のすべての値を見つけるために、しかし

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

:あなたはこのような何かを経由して気にすぎずにmissontoものを得ることができるように、プラスあなたのdataステートメントに必要な変更でしょうまだ通常はxtraデータセットに行かない場合は、にはの値が使用されていることを把握しておく必要があります。その後、データステップの最後に残りの部分を新しいハッシュにコピーしますそのオブジェクトを出力します。

N.B.現在のコードでは、すべての行が参照変数の値が欠落していても、&ontoデータセットに出力されます。

0

これを行うのは少し難しいですが、ここではどのように行うことができるかのサンプルアイデアがあります。

最初のハッシュオブジェクトと同じように、別のハッシュハッシュオブジェクトを作成します。 2番目のオブジェクトからは、すでに一致したアイテムを削除します。最後に、2番目のオブジェクトをデータセットに出力するだけです。それは、ハッシュオブジェクトのためにメモリを奪うが、その最初の試みを取る。

(任意のエラーのコードと申し訳ありませんが実行されませんでした)

%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; 

私は手遅れ出回っている第2のハッシュが、今日ではありません保存データのように少しメモリを消費するために、これを向上させることができます。これが少し助けてくれることを願っています。

+0

1対1のマージであれば、このアプローチは1つのハッシュテーブルだけでは機能しませんでしたか? Find()が成功した場合は、各レコードを一度読み取るだけでよいので、remove()を実行できます。 – Quentin

+0

@クエンティンあなたは正しいですが、より一般化されたアプローチをしました。 one2oneの場合は、1つのハッシュにすることができます。 – fl0r3k

+0

このアプローチでは、&によって値が重複する可能性がありますが、&からの値によって重複を処理できませんでした。 – 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; 

あなただけの変数「から」は、コードを変更するのに十分な単純なものでしょうし、新しいデータに非欠損値を含めるか、または削除したい場合。

誰かがこれを行うより効率的な方法を知っている場合は、提案を投稿してください。

関連する問題