SASでの柔軟な実装を行う際にマクロは大変役立ちます。

SASにおいてマクロというのは、DataステップやProcステップ等による一連の処理を1つの(所謂)プロシージャ化でき、又、そのプロシージャ内で条件分岐や繰り返し処理が自由度高く行うことができる仕組みです。
要は、DataステップやProcステップをより効率良く、自由度高く実装できる仕組みがマクロです。マクロを使う事で、ハードコーディングを減らし、保守性の高い実装が行えたりします。

そのマクロに関連するものでマクロ変数というものがあり、これは(データセットの列名でなく)他のプログラミング言語で意味付いている「変数」のイメージです。

今回はマクロの使い方を使用例を通して説明します。
※マクロ変数に着目した説明は下記リンクに記載しています。

マクロ使用例:
 データセットagg_mstの要件でデータセットtrnを集計

1.入力データセットを用意

今回は下記データセットが既存というケースを考えます。
行いたい事は「データセットtrnについて、列typeの値毎に列valueの合計を算出する。但しそれぞれの集計対象は、列ymdの範囲(期間)が(データセットagg_mstの)ymd_fromからymd_toまで。」です。
agg_mstの各行には「このtypeは、この期間(from/to)で(trnのデータについて)集計を行ってほしい」という集計要件が格納されている形です。
そのagg_mstの要件でtrnを集計するマクロを今回は作ってみたいと思います。

(もし、今回のようなtrnの集計をマクロを使わないで行う場合、「type=aならばここからここまでの期間」みたいな集計要件をハードコーディングする必要がありそうです。ですが、マクロを使う事によって、agg_mstのように要件をデータセット化して対応ができるので、例えば集計要件が今後変わる際もプログラムの手直しは不要になり、つまりは保守性が高まります。)

/* 集計要件のデータセット */
data agg_mst;
	input type $ ymd_from ymd_to;
	cards;
		a 20230101 20230103
		b 20230101 20230104
		c 20230102 20230104
	;
run;

/* 集計対象のデータセット */
data trn;
	input type $ ymd value;
	cards;
		a 20221231 1
		a 20230101 10
		a 20230102 100
		a 20230103 1000
		a 20230104 10000
		b 20221231 1
		b 20230101 10
		b 20230102 100
		b 20230103 1000
		b 20230104 10000
		c 20221231 1
		c 20230101 10
		c 20230102 100
		c 20230103 1000
		c 20230104 10000
	;
run;
agg_mst
trn

2.集計用のマクロを定義

下記の形で集計ロジックが書けます。
このように、集計要件(各typeの集計期間)をハードコーディングせずに各typeそれぞれ別々の集計期間を集計することができます。
定義内のコードについて要点を言うと、
 ・call symputx(x, y):xというマクロ変数名を(trimの上)定義し、値をyにする。
 ・cats(x,y,…):引数を文字結合
 ・_N_:入力データセット(set xxx)の行番号
 ・end=eof:入力データセットの最終行になったら変数eofを1にする
 ・%put _USER_;:ユーザが定義したマクロ変数等の一覧をログに表示
 ・%do i=1 %to n;~end;:(1からnまでの値が入る)マクロ変数iを定義の上、内部に記載した処理を繰り返す。

%macro agg_trn;
	/* agg_mstの情報をマクロ変数化 */
	data _null_;
		set agg_mst end=eof;
		call symputx(
			cats("type_", _N_),
			type
		);
		call symputx(
			cats("from_", _N_),
			ymd_from
		);
		call symputx(
			cats("to_", _N_),
			ymd_to
		);
		if eof;
			call symputx("agg_mst_len", _N_);
	run;
	
	/* マクロ変数を確認 */
	%put _USER_;
	
	/* 集計 */
	proc sql;
	select
		type,
		sum(value) as sum_value
	from trn
	where 
		1=2
		%do i=1 %to &agg_mst_len.;
			or (
				type = "&&type_&i.."
				and ymd between &&from_&i.. and &&to_&i..
			)
		%end;
	group by type
	order by type
	;
	quit;
%mend;

3. マクロの実行

%agg_trn;
%put _USER_; の実行結果の一部(マクロ変数の個所を抜粋)
集計結果

By clear

データエンジニア・機械学習・分析等を主とし、Webアプリ開発も行っているフリーランスです。