sas について
SAS コードの作成とレビューを支援する静的な言語スキルです。DATA ステップ、PROC SQL、マクロ、一般的なプロシジャを扱いますが、コードの実行や外部システムへのアクセスは行いません。
主な機能
- 01DATA ステップと PROC SQL の指針
- 02マクロ言語の記述パターン
- 03一般的な PROC と ODS の手順
- 04ファイル I/O とフォーマット
- 05スタイルと移植性のルール
- 06ログと警告のレビュー
活用シーン
- 01SAS のデータ変換を作成
- 02SAS プログラムをレビューまたはデバッグ
- 03PROC SQL のクエリとレポートを作成
- 04マクロのよくある問題を確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ sasjs/ skills --skill sasインストール後、Claude Code で/sasを入力して読み込まれたか確認します。
詳細
SAS 言語
慣用的で、本番品質の SAS コードを記述します。このスキルでは、あらゆるフレームワークに依存しない SAS 言語そのものを扱います。
対象範囲
- DATA ステップのプログラミング(SET/MERGE/BY、RETAIN、配列、DO ループ、ハッシュオブジェクト、first./last. 処理)
- PROC SQL(結合、サブクエリ、ビュー、CONNECT TO を使用したパススルー)
- マクロ言語(%macro/%mend、マクロ変数、%local/%global、条件付き %IF ロジック、引用関数 %STR/%NRSTR/%BQUOTE、CALL SYMPUTX)
- よく使用される PROC:SORT、MEANS/SUMMARY、FREQ、TRANSPOSE、REPORT、PRINT、CONTENTS、DATASETS、FORMAT、IMPORT/EXPORT
- フォーマットと入力形式(PROC FORMAT によるユーザー定義形式、ピクチャ形式)
- ODS 出力(HTML、PDF、RTF、Excel、OUTPUT 出力先)
- ファイル I/O:LIBNAME、FILENAME、INFILE/INPUT、FILE/PUT
ワークフロー
SAS コードを生成するすべての依頼(新規プログラム、編集、デバッグ)で、次の手順を適用します。
- 依頼を分析します。 入力(データセット、列、マクロ変数、プラットフォーム(SAS 9 と Viya のどちらか))を特定します。必要な出力(データセット、レポート(ODS)、マクロ変数、ファイル)を確認します。依頼が曖昧な場合は、前提を明示して作業を進めます。
- コードを作成します。 以下のスタイルルールに従い、正しく動作する最小限のプログラムを記述します。2 レベルのデータセット名を使用し、文字変数には明示的に
lengthを指定し、マクロ内では%localを使用し、proc sqlにはquit;を使用します。手作業で重複を除去するよりもproc sort nodupkeyを優先します。 - 実行します(または実行方法を説明します)。 SAS セッションが利用できる場合は、コードを送信してログを取得します。利用できない場合は、「よくある落とし穴」のリストに照らしてコードを頭の中で追跡し、検証できなかった手順を明記します。
- ログを確認します。
WARNING:またはERROR:は無視する注記ではなく、修正すべき欠陥として扱います。よくある原因は、初期化されていない変数、暗黙の数値から文字への変換、暗黙の length=8 による切り捨て、「no observations」、解決されないマクロ参照、読み取り専用の自動マクロ変数です。余計なNOTEも、妥当な範囲で削除します。 - 落とし穴を再確認します。 最終コードを「よくある落とし穴」のリストと照らし合わせて再確認し、該当する点を修正するか注記します。
入力: 自然言語による依頼または .sas ファイル。必要に応じてサンプルデータやログの抜粋も含みます。出力: 慣用的な SAS コード(2 つのスペースでインデントし、run;/quit; で終了)と、必要に応じて対処した落とし穴や前提に関する短い注記。検証: 返却するコードは頭の中でログを確認した際に WARNING/ERROR がゼロであり、実行できる場合は実際の実行でもクリーンなログが生成されます。
必須事項:WARNING を出さない
生成する SAS コードは、ログに WARNING を一切(ERROR も一切)出さずに 実行できなければなりません。WARNING: はすべて欠陥として扱います。初期化されていない変数、暗黙の型変換、警告につながる切り捨て、「no observations」、解決されないマクロ参照などが該当します。警告が本当に避けられない場合は、理由をコメントに記載したうえで、明示的なオプションなどを使用して意図的に抑制します。同様に、妥当な範囲で余計な NOTE も避けます。
スタイルルール
以下は @sasjs/core のコーディング規約です。すべての SAS コードに適用してください。
- 1 行に 1 つのステートメントを記述します。インデントは 2 つのスペースとし、タブや末尾の空白は使用しません。
- 複数のオペランドを取るステートメント(
%local/%global、length、attrib、retain、array、format/informat、label、keep/drop、var、rename)は、すべてのオペランドを列挙した 1 つのステートメントにまとめます。行の長さ制限を守るためだけに、同じステートメントを複数に分けて重複させないでください(%localを 2 行にする、lengthステートメントを 2 つにするなど)。行が制限を超える場合は、次の行に続けてください。ステートメントはセミコロンで終わるため、続きの行は文字数に含まれません。 - 1 行は 80 文字以内とします。改行コードは Unix(LF)、文字コードは UTF-8 とします。
- 非 ASCII 文字や特殊文字は一切使用しないでください。すべての SAS インストール環境や文字エンコーディングで最大限の互換性を確保します。
- ステップは必ず
run;で終わらせます。proc sql(および CAS 接続プロシージャ)では、Viya でWARNING: You cannot disconnect or terminate session ...が発生するのを防ぐために、quit;が必須です。 - すべてのデータセット参照は 2 レベルにします(
blahではなくwork.blah)。これにより、DATASTMTCHK=ALLKEYWORDSとアクティブなUSERライブラリによる問題を防ぎます。 - 文字変数にはデフォルト値に頼らず、明示的に
length/attribを指定します(暗黙の length=8 による切り捨てを防ぎます)。 - 明確さのため、リテラルサフィックスを使用します(
'01JAN2020'd、'12:30't)。 - 手動で重複排除を行うロジックより、
nodupkeyを指定したproc sortを優先します。 - マクロ:
- パラメーターがない場合も、かっこを付けて定義します。
%macro x();とし、%macro x;とはしません。 - 終了時の
%mend;にはマクロ名を繰り返し記述します。 - マクロ呼び出しの末尾にはセミコロンを付けません。
%my_macro()とし、%my_macro();とはしません。 - 必須パラメーターは位置指定、オプションのパラメーターはキーワード形式(
var=)にします。 - マクロ名は小文字の動詞-名詞形式にします。
- マクロ変数の末尾にピリオドを付けません(
&varとし、&var.とはしません)。ただし、正しく解決されないのを防ぐために必要な場合は除きます。 - マクロ変数名では大文字と小文字が区別されません。
&Foo、&FOO、&fooはすべて同じシンボルに解決されます(同様に、値ではなく名前を受け取る%symexist/%superq/symgetの引数でも区別されません)。大文字小文字の不一致をバグとして追跡しないでください。原因になることはありません。 - 意図的にグローバルにする場合を除き、すべてのマクロ変数を
%localにします(グローバル変数には、衝突を避けるためアプリケーションのプレフィックスを付けます)。DATA ステップではsymputではなくcall symputxを使用します。 - マクロ内のコメントには
/* */を使用します(アスタリスク形式のコメントはマクロにコンパイルされます)。 - マクロロジックの条件判定には、
&var=ではなく%length(&var)=0のチェックを使用します(空の値との比較は安全ではありません)。
- パラメーターがない場合も、かっこを付けて定義します。
- 名前の衝突を避けるには、ハードコードした名前ではなく
%sysfunc/&syslastベースの WORK テーブルを使用します(例:data &output; set &syslast; run;)。 - WORK ライブラリはセッション終了時に自動的にクリアされます。セッションが終了すると、SAS は WORK 内のすべてのテーブルを削除します。そのため、通常の一時テーブルでは明示的なクリーンアップ(
proc datasets lib=work nolist; delete ...; quit;)は不要です。これを追加したり、レビューで省略を欠陥として指摘したりしないでください。一時ファイルが大きい、または大量にあり、実行中にディスク容量を圧迫するリスクがある場合に限り、明示的にクリーンアップします。その場合は、セッション終了時の削除まで残すのではなく、不要になった時点ですぐに削除してください。 - マクロ外の条件付きコードは使用しません。プラットフォーム分岐や条件付きで実行するブロック(例:
%if %mf_getplatform()=VIYA %then %do; ... %end;)は、%macro ... %mendで囲み、マクロを呼び出してください。プログラムレベルの%ifは、一部の実行コンテキスト(ジョブ/スケジューラー/テストハーネス)で失敗し、スコープの漏れを隠すことがあります。
移植性に関する注意
- SAS 9.4 と Viya でコードが異なる場合は、その違いに注意してください(例:CAS アクションとプロシージャ、sashdat の読み込みに使う
proc casutil、制限付きサーバーでは X コマンドが使えないことなど)。 - 指示がない限り、物理パスのハードコードやエンジン固有のオプションは避けてください。
- if/else ロジックを含むマクロ外のコードは使用しません。分岐ブロックは
%macro ... %mendで囲み、呼び出してください。マクロ外の%if/%elseは、すべての SAS 環境で期待どおりに動作するとは限りません。
修正前/修正後の例
各ペアでは、WARNING が発生しやすい、または欠陥につながりやすい一般的なパターンと、ログの問題に対処する慣用的な修正を示します。
DATA ステップ:未初期化変数+暗黙の長さによる切り捨て
変更前 - region は参照されていますが、値が代入されておらず、set で取り込まれてもいないため、ログに WARNING: Variable region is uninitialized と表示されます。また、name はソースの first_name の長さ(多くの場合 $8)を引き継ぐため、連結した値が通知なく切り捨てられます。
data work.customers;
set work.source;
region = upcase(region); /* region not in work.source */
name = catx(' ', first_name, last_name); /* truncated to source length of name */
run;
変更後 - region を set で取り込むか、明示的に値を代入します。また、set の前に明示的な length を指定して name の長さを広げることで、catx による切り捨てを防ぎます。
data work.customers;
length name $ 50;
set work.source; /* region must exist in work.source */
region = upcase(region);
name = catx(' ', first_name, last_name);
run;
PROC SQL:暗黙の型変換+直積
変更前 - 文字型の id と数値型の cust_id を結合すると、NOTE: Character values have been converted to numeric が出ます(オプションによっては WARNING)。また、結合キーが欠損していると、直積が発生して結果が膨れ上がるおそれがあります。
proc sql;
create table work.joined as
select a.*, b.balance
from work.orders a, work.accounts b
where a.id = b.cust_id;
quit;
変更後 - 明示的に length を指定するかキャストして型を一致させ、明示的な内部結合を使用し、キーが欠損している場合に直積が起きないようにします。
proc sql;
create table work.joined as
select a.id, a.amount, b.balance
from work.orders as a
inner join work.accounts as b
on a.id = input(b.cust_id, 8.) /* explicit cast; or fix upstream length */
;
quit;
キー列に両側で正当に重複が存在する場合は、先に集約または重複を除去してください。意図しない 1 対 1 の結合に頼ってはいけません。
マクロ:%local の欠落+安全でない空チェック
変更前 - マクロ内の %let によって、%local がないため dsid がグローバルスコープに作成されます。また、%if &filter= は安全ではありません。&filter が空の場合、%if = %then と展開され、正常な分岐ではなく構文エラーになります。
%macro apply_filter(filter=);
%if &filter= %then %do;
data work.out; set work.in; run;
%end;
%else %do;
data work.out; set work.in; where &filter; run;
%end;
%let dsid = &syslast;
%mend apply_filter;
変更後 - %local dsid によって一時変数をマクロスコープ内に保持します。%length(&filter)=0 を使うと空チェックを安全に行えます。また、マクロ定義に括弧を付け、%mend で名前を繰り返します。
%macro apply_filter(filter=);
%local dsid;
%if %length(&filter)=0 %then %do;
data work.out; set work.in; run;
%end;
%else %do;
data work.out; set work.in; where &filter; run;
%end;
%let dsid = &syslast;
%mend apply_filter;
複数オペランドを取るステートメント:重複させず、1 つのステートメントにまとめる
変更前 - 関連するオペランドに対して %local ステートメントが 2 つ、length ステートメントが 2 つあります。これは不要な繰り返しです。オペランドは 1 つの宣言にまとめます。
%local dbg libref1 libref2 loglocation fname1 fname2;
%local jobstate err_httpcode err_msg;
data work.staged;
length customer_id 8;
length customer_name $ 50;
set work.source;
run;
変更後 - 各グループを 1 つのステートメントにまとめます。1 つのステートメントが 80 文字を超える場合は、継続行で折り返します(ステートメントはセミコロンで終わるため、折り返した行は文字数に含まれません)。
%local dbg libref1 libref2 loglocation fname1 fname2
jobstate err_httpcode err_msg;
data work.staged;
length customer_id 8 customer_name $ 50;
set work.source;
run;
これは、オペランドのリストを受け取るすべてのステートメントに当てはまります。%local/%global、length、attrib、retain、array、format/informat、label、keep/drop、var、rename が該当します。
レビュー時に指摘すべきよくある落とし穴
- 意図しない多対多の MERGE
- 自動変数
_ERROR_/暗黙の RETAIN による予期しない動作 - マクロのタイミングに関する問題:
¯ovarが存在する前に参照する、%ifで DATA ステップ変数を評価する(代わりにif/symgetを使用してください) - 自動マクロ変数(
&syscc、&syswarningtext、&syserrortext、&sysdate、&sysuseridなど)は読み取り専用です。上書きしようとすると(例:%let syswarningtext=;またはcall symput('syscc',...))、ERROR: Unable to assign value to a macro variable that is read only(または同様のエラー)が発生します。決してこれらを「クリア」しようとしないでください。 - 最初の代入で暗黙に length=8 となることによる切り捨て
proc sqlの直積に関する警告
制限事項
このスキルは静的な言語リファレンスであり、SAS コードの作成とレビューに関するガイダンスを提供します。SAS コードの実行、シェルコマンドの実行、ファイルシステムへのアクセス、データベースへの接続、ネットワークリクエストの送信は行いません。コード例はすべて説明用であり、ユーザーが SAS セッションに送信する必要があります。「File I/O」、「PROC SQL」、「command」、「execution」などの用語は SAS 言語の概念(ファイル処理ステートメント、SQL プロシジャ、マクロの実行コンテキスト)を指し、このスキルが行うオペレーティングシステムレベルの操作を意味するものではありません。