SASを使う方であればよく使うput関数。引数にフォーマットをあてて文字列として出力する関数ですが、フォーマットの文字列を変数に置き換えて動的にフォーマットを変えたいと思ったことはあるのではないでしょうか?(私はあります。)でもput関数ではできません・・・・。どうすればよいでしょうか?
具体的にやりたいこと
以下のコードを実行するとaに格納された日付値にフォーマットが割り当てられて、変数bには2020/05/26が格納されます。しかし仕様変更によりこの日付の形式を変える必要がでてくるかもしれません。その場合はどうしましょう?
data test;
a='26may2020'd;
b=put(a,yymmdds10.);
run;
まあput関数の第二引数を書き換えればよいのですが、引数をマクロ変数に置き換えて動的にフォーマットを変えたほうが、プログラム本体を書き換える必要がないので安全です。以下のようにするとletステートメントの部分のみを書き換えればよいので、プログラム本体を書き換える必要がなく、保守しやすくなります。
/*フォーマットの指定*/
%let fmt=%str(jdateymd18.);
/*----プログラム本体--------*/
data test;
a='26may2020'd;
b=put(a,&fmt.);
run;
ではデータセットの値に応じてフォーマットを切り替えたい場合はどうでしょう?データセットの値からフォーマットの文字列を生成して、それをput関数の引数とすることが思いつきます。
実際にやってみましょう。以下のコードは変数fmtにフォーマットを格納してput関数の引数と指定しています。
data test;
a='26may2020'd;
fmt="jdateymd18.";
b=put(a,fmt);
run;
これは構文エラーとなります。put関数はコンパイル時、つまりデータセットを作成する前に出力形式を読み込むため、データセットの値から出力形式を参照することができません。マクロ変数とマクロは一番最初にSASが解釈するため、マクロ変数であれば出力形式を読み取ることができます。
putn関数を使う
データセットの値から出力形式を参照したい場合は、putn関数を使いましょう。putn関数は数値にフォーマットを当てる関数で、プログラム実行時に出力形式を指定できます。関数実行の度に出力形式を読み取るためputn関数はput関数よりも低速です。
上記のプログラムは以下のように書き換えると正常に動作し、変数bには2020年5月26日が格納されます。
data test;
a='26may2020'd;
fmt="jdateymd18.";
b=putn(a,fmt);
run;
putn関数であればDATAステップで演算や文字列連結を行うことでフォーマット名を動的に生成し、任意の変数に割り当てることができるようになります。
わかりやすい例として、過去記事で紹介した有効数字を出力する関数にて使用しています。
有効数字はputn関数で文字列型に変換しています。この時丸めたい数値の桁数に応じてフォーマットの文字列を生成し、それをputn関数に読み込んでいます。put関数では動的にフォーマットを変えることができないため、代わりにputn関数を使用しています。