2017-01-05 14 views
2

データステップで呼び出しを実行してマクロを実行しています。 私のデータステップから欲しいものは以下の通りです:実行時に毎回出力変更が実行される

既存のすべての列に(マクロを介して)新しい列を追加し、最後に2つの列の合計である新しい列を追加します。 マクロなしでも可能ですが、私はSASに慣れていないため、マクロのロジックを理解してexecuteを実行したいので、このようにしたいと思います。 (後 :

data values; 
input a1 a2 b1 b2; 
datalines; 
1 0 3 10 
0 5 6 11 
7 8 9 0 
; 
run; 

と、このマクロ:その後、

%macro loop1(myDataset); 
proc contents data=&myDataset. out=Col_Names (keep=Name) noprint; 
run; 
proc sql noprint; 
select count(Name) into :length from Col_Names; 
quit;             
    %do j = 1 %to &length; 
      data &myDataset.; 
      set &myDataset.; 
      n&j=0; 
      run;      
    %end; 
%mend; 

次のデータのステップは、異なる出力、私はそれを実行する最初の3回を作成し

それでは、私は次の表を持っているとしましょう毎回私は元のデータステップをデータラインで再実行します)

data values; 
set values; 
if _n_=1 then call execute('%loop1(values);'); 
test=sum(a1,a2); 
run; 
エラーで

最初の実行結果:

WARNING: Apparent symbolic reference LENGTH not resolved. ERROR: A character operand was found in the %EVAL function or %IF condition where a numeric operand is required. The condition was: &length ERROR: The %TO value of the %DO J loop is invalid. ERROR: The macro LOOP1 will stop executing.

セカンドランの結果、私がしたい正確に何で:

A1、A2、B2、B2、テスト、N1、N2、N3、N4

そして、上の3回目から、出力がまま:

A1、A2、B2、B2、テスト、N1、N2、N3、N4、N5

望ましくないとn5が入っています。

2回目の出力から常に出力を得るにはどうすればよいですか?

答えて

2

call executeを使用してマクロを呼び出すときに、次の使用上の注意に従って%nrstr()でそれらをラップすることをお勧めします。

http://support.sas.com/kb/23/134.html

これは時期尚早マクロの実行を防止 - あるいは少なくとも、任意の依存を待つためにそれを強制的に準備が整うマクロ変数、つまりINTO:句にlengthという変数があります。

proc sql noprint; 
select count(Name) into :length from Col_Names 
    where upcase(name) ne 'TEST'; 
+0

ありがとうございます!しかし、結果は直接的に3番目のものであり、私は2番目のものを望んでいます。 – Zap

+0

回答が更新されました。 –

+1

しかし、私のマクロの後にデータステップで作成された場合、どのように 'テスト'がproc SQL内にあるのでしょうか?この場合、マクロは動作しますが、新しいカラムがあるたびにそれを適応させる必要があります。他に方法はありませんか? – Zap

1

それが失敗した理由:あなたが望む結果を得るために、あなたはまた、次のように、あなたのSQLの手順で「試験」変数を除外する必要が

data values; 
    set values; 
    if _n_=1 then call execute('%nrstr(%loop1(values);)'); 
    test=sum(a1,a2); 
run; 

あなたコードはまったく変数 'n1'などを'values 'データセットに追加しません。あなたの最後のデータステップの後にマクロをスケジュールします。これはあなたが望むものではありません。

は、あなたの最後のデータのステップ

data values; 
    set values; 
    *&new_columns; 
    if _n_=1 then call execute('%loop1(values);'); 

    test=sum(a1,a2); 
    n2=9874; 
run; 

への割り当てを追加するインスタンスの試してみて、あなたはときにマクロが実行'n2'のためのあなたの値が上書きされるので、それは効果がありません表示されます。あなたは何ができるか

select <something> into :<variable> separated by <separator>を使用すると、割り当てを含むマクロ変数を作成することができます。

proc contents data=values noprint out=Col_Names(keep=varnum); 
run; 
proc sql noprint; 
    select 'n'|| strip(put(varnum, 8.)) ||'=0' 
    into :new_columns separated by ';' 
    from col_names; 
quit; 

あなたのデータ段階でこの変数を使用することができます。

data values; 
    set values; 
    &new_columns; 

    test=sum(a1,a2); 
    n2=9874; ** Now this has effect **; 
run; 
+1

マクロを避ける方が良いですが、OPは彼が "まさしくこのように"したいと言っていました –

+0

''この方法では決して動作しません。データステップがコンパイルされ、その時点でデータステップに変数を追加することはできません。 (より技術的に言えば、その時点でプログラムベクトルが作成されます。) –

0

それが失敗した理由をSASマクロを実行するときに、あなたのデータのステップが実行され、マクロが上に生成したコードを推進しているということですスタック。その後、データステップが終了した後、実際に生成されたPROCおよびDATAステップを実行します。

マクロが実行されると、PROC SQLステップが生成されますが、データステップがまだ実行されているため、ステップはまだ実行されません。マクロは%DOループを実行し、マクロ変数LENGTHが存在しないか、データステップを開始する前に存在していたマクロ変数の値を使用するため、エラーが生成されます。

このラップを防ぐには、%NRSTR()で呼び出します。これにより、マクロ呼び出し自体がデータステップが停止した後にスタックにプッシュされます。

call execute('%nrstr(%loop1)(values);'); 

実際の例では、CALL EXECUTEはまったく必要ありません。データステップを実行した後にマクロを呼び出すだけです。

data values; 
    set values; 
    test=sum(a1,a2); 
run; 
%loop1(values); 

また、新しいTEST変数にフラグ変数を設定したくない場合は、データステップの前にマクロを実行します。

関連する問題