SASには、コードの繰り返しを回避するための多くのオプションがあります。このように、実際にはPythonによく似ていますが、別のコンパイル手順があるため、実行方法が少し異なります(したがって、直接質問するようにWHEREとだけ言うことはできません)。
まず、マクロ変数があります。テキストを数回繰り返すだけの場合は、次のようにマクロ変数でテキストを定義できます。
%let condition=X in (1,10,100,1000);
マクロ変数は、作成したテキストであるかのように扱われます。法典として含めることを意図していない限り、引用符やその他のテキスト修飾子は必要ありません。
%let condition=X in ('A','B','C');
合法ですが
%let condition="X in ('A','B','C')";
おそらくあなたが望むものではないでしょう(とにかく、それを文字列として評価したいのでなければ)。
マクロ変数を使用すると、データステップで大量のコードを生成し、それを含めることもできます。たとえば、条件のリストを含むデータセットがある場合は、次のように適用できます。
data conditions;
format condition $50.;
input condition $;
datalines4;
if x = 15 then y=5;
if x = 20 then y=10;
if x = 20 and z = 5 then y=15;
if x = 20 and z = 10 then y=20;
;;;;
run;
proc sql;
select condition into :condlist separated by ' ' from conditions;
quit;
data want;
set have;
&condlist;
run;
これにより、「conditions」データセットから条件が取得され、マクロ変数「&condlist」にプッシュされます。PROC SQL呼び出しは、それをマクロ変数に取り込む最も簡単な方法ですが、他にもあります。CALL SYMPUTは、データステップで実行することもできます。または、テキストファイルに書き込んでから、テキストファイルをコードとして%インクルードすることもできます。これは、マクロへの呼び出しを生成することにより、高度なプログラミングでより一般的に使用され、条件データセットはマクロパラメーターを提供します。この場合、あなたはマクロを持っているかもしれません
%macro cond(x=,y=,z=);
if x=&x and z=&z then y=&y;
%mend cond;
次に、x、y、z値のみのデータセットからcondへの呼び出しを生成できます。
proc sql;
select cats('%cond(x=',x,',y=',y,',z=',z,')') into :condlist separated by ' ' from conditions;
quit;
同じように使用します。
一般に、マクロプログラミングは、コードクリープを回避するための優れたソリューションです。マクロは一度書き込まれると、異なるパラメーターを使用して複数回実行できます。マクロは、データステップ内で実行される1行のコード(上記のような)から、複数のDATAおよびPROCステップを含む数百行までのどこでもかまいません。マクロプログラミングはそれ自体が複雑なトピックであり、さらに読む価値があります。
SASで関数を作成することもできます。PROC FCMP(関数コンパイル)を使用すると、かなり複雑な関数を記述して、データステップまたはPROCステートメントで実行することができます。 http://www.lexjansen.com/pharmasug/2011/tu/pharmasug-2011-tu07.pdfは、9.2を使用している場合にFCMPを開始するのに適した場所です。9.3をお持ちの場合、FCMPの新しいものを示す論文はまだ見ていません(ただし、いくつかある可能性があります)。FCMPはかなり新しいため、SASの各反復にはまだ多くの変更があります。
条件を実行するためのFCMPの例を次に示します。
proc fcmp
outlib=work.funcs.Test; /* where will the functions be saved */
function condition(x); /* declare a function returning a number */
if x in (1,10,100,1000) then return(1);
else return(0);
endsub;
quit;
data have;
do x = 1,5,10,20,100,150,1000,1500;
output;
end;
run;
options cmplib=work.funcs;
data want;
set have;
if condition(x) then output;
run;
また、データセットからコードを直接実行できるCALLEXECUTEステートメントもあります。同じCONDITIONSデータセットを使用する:
data _null_;
set conditions end=eof;
if _n_ = 1 then call execute('data want; set have;');
call execute(condition);
if eof then call execute('run;');
run;
これにより、マクロ変数の例と同じコードを使用して、データヌルステップの直後に実行されるデータステップが効果的に構築されます。呼び出しの実行の動作は少し異なるため、この例では違いはないはずですが、タイミングに問題を引き起こす可能性のある(または有利な可能性のある)問題がいくつかあります。どちらを使用するかは、状況によって異なります。特にCALLEXECUTEの場合は、ドキュメントとオンラインペーパー(最も一般的にはSUGIペーパー)を読んで詳細を確認してください。
マクロ変数またはCALLEXECUTEを介してコードを直接実行することに加えて、壁紙コードを回避するためのタスクを実行する他の多くの方法があります。たとえば、上記のifステートメントをより簡単に実行するために、フォーマットを使用できる場合があります。フォーマットは、ある値を別の値に変換します。最も一般的には、「DOLLAR6.2」のようなものがあり、3.5から3.50ドルが得られます。ただし、フォーマットを使用して、if-this-then-that式を置き換えることもできます。XとYのみ(およびZ条件がない)の場合、次の条件データセットがあれば、これを行うことができます。
data conditions;
input x y;
datalines;
1 5
2 10
3 20
4 50
5 100
;;;;
run;
data for_fmt;
set conditions;
rename x=start y=label;
fmtname='XTOY';
type='i'; *type=i means numeric informat, so numeric to numeric conversion. Informat = to numeric, Format= to character.;
run;
proc format cntlin=for_fmt;
quit;
data want;
set have;
y = input(x,XTOY.);
run;
xをyに変換する1行のコードがあります。(もちろん、フォーマットを設定するコードは少しありますが、メインコードから分離して、cの.hファイルのようにコードのセットアップ部分に含めることができます)。
ハッシュテーブルルックアップもあります。これは、より複雑な変換(1対多または多対1)がある場合に非常に役立ちます。これらは、サウンドと同じように機能します。ハッシュテーブルをメモリにロードしてルックアップを実行します。 http://support.sas.com/rnd/base/datastep/dot/hash-getting-started.pdfは、開始するのに適した場所の1つです。
最後に、コードの繰り返しを回避する1つの良い方法は、使用する個別のデータセットを少なくすることです。SASデータのステップとプロシージャでは、「BY」ステートメントを使用できます。これは、BY変数のそれぞれの異なる値を効果的に個別のデータセットとして扱うことを意味します。技術的には1つのデータセットであるため、変数名と長さは一致する必要がありますが、類似したデータのデータセットが多数あり、それぞれに対して同じアクションを実行する場合は、BYステートメントを使用して複数回ではなく1回実行できます。 。
たとえば、データセットSASHELP.CARSがあるとします。車のメーカーごとに個別に計算することをお勧めします。次のいずれかを実行できます。
data acura;
set sashelp.cars;
if make='ACURA';
run;
data honda;
set sashelp.cars;
if make='HONDA';
run;
次に、各データセットでコードを個別に実行します。ただし、それを行うためのよりSASsyな方法は、BYステートメントを使用することです。
proc means data=sashelp.cars;
by make;
var mpg_city mpg_highway;
run;
これで、メーカーごとに個別のページが表示されます。BYステートメントはデータステップ処理でも使用できます。新しいMAKEの最初のレコードまたはMAKEの最後のレコード(値が変更される直前のレコード)にいるかどうかを示す変数FIRST.makeおよびLAST.makeを取得します。これにより、ベースの処理を実行できます。データセットのBYグループ内の場所(たとえば、if first.make then counter=0;
新しい値を取得するたびにリセットされるカウンターを使用できるようにしmake
ます)。BYグループの唯一の注意点は、データセットをBY変数で並べ替える必要があることです。それを使用する前に(またはその変数にインデックスを付けるか、あるいはその両方)。これは、ブートストラップサンプルや、ほぼ同一のデータセットが多数あり、それらに対して同一のアクションを実行するその他のプロセスの分析に非常に役立ちます。