2010年3月30日火曜日

SAS9.2から追加になったFCMPプロシジャを使ってみる

SAS version 9.2からユーザー独自の関数を作成できるプロシジャ
FCMPプロシジャが新しく加わりました。

簡単な構文ですが以下に解説します。
今回は誕生日と現在日付(共にSAS日付値)を引数に与えると
年齢「○○歳」と結果を返す関数を作成してみます。

/*--------- 関数作成編 ---------*/
libname sasfunc "e:\sasfunc";

proc fcmp outlib=sasfunc.functions.test;

function getAge(today, birthday) $;
_tmp1 = intck('YEAR', birthday, today);
_tmp2 = (month(birthday)*100 + day(birthday)) - (month(today)*100 + day(today));
if _tmp2 > 0 then age = _tmp1 -1;
else age = _tmp1;
return(put(age, best.)||'歳');
endsub;

run;
/*----------------------------------*/

▼まず作成した関数を保存するフォルダにLIBRARY参照名を定義します

▼FCMPプロシジャを使ってユーザー定義関数を作成します
・outlib=オプションで<ライブラリ参照名>.<データセット名>.<パッケージ>の順に指定します
・functionステートメントに 関数名(例ではgetAge)、引数を指定します。
戻り値が文字値の場合は最後に「$」を指定します。
・通常のデータステップと同じ文法で変数を作成します。
・return()ステートメントで()内に返す戻り値を指定します。
・endsubステートメントで関数定義を終了します。

▼実行すると以下のようなログが出力され、関数が登録されます。

NOTE: Function getAge saved to sasfunc.functions.test.
NOTE: PROCEDURE FCMP 処理 (合計処理時間):
処理時間 2.00 秒
CPU 時間 0.14 秒


(登録は指定したライブラリにデータセットとして登録されます。)

次に作成したユーザー定義関数を使用してみましょう。

/*--------- 関数使用編 ---------*/
options cmplib = sasfunc.functions;

data _null_;

today = '2may2010'd;
birthday= '2may1977'd;

age = getAge(today, birthday);

put age=;
run;

/*----------------------------------*/

▼options cmplib = <ライブラリ参照名>.<データセット名>
登録した関数が保存されているライブラリ参照名とデータセット名を指定します。

▼あとはDATAステップ内で従来のSAS関数と同様に使用するだけです。
他にもwhereステートメント内や、いくつかのプロシジャ内でも使えるようです。
実行ログは以下のようになりました。

24 options cmplib = sasfunc.functions;
25 data _null_;
26
27 today = '2may2010'd;
28 birthday= '2may1977'd;
29
30 age = getAge(today, birthday);
31
32 put age=;
33 run;


age=33歳
NOTE: DATA ステートメント 処理 (合計処理時間):
処理時間 0.62 秒
CPU 時間 0.03 秒


以上、簡単なFCMPプロシジャの使い方でした。

ではFCMPプロシジャとユーザー定義関数にはどのような利点があるでしょうか?
米SASサポートサイトのFCMPプロシジャのoverviewに次の文章があります

This feature enables programmers to more easily read, write, and maintain complex code with independent and reusable subroutines.
You can reuse the PROC FCMP routines in any DATA step or SAS procedure that has access to their storage location.

まとめると
・独立した再利用可能な関数によって複雑なコードの読み書き、保守がやりやすくなる。
・定義データにアクセスできればどこからでもDATAステップ、やプロシジャで再利用できる。

今まででもマクロプログラムでこれに近いことができますが
FCMPプロシジャを使えばより独立性と再利用性が高まるといった感じでしょうか。
とはいえ従来と毛色の違う新しい機能ですし、開発プロジェクトに導入するには
コーディングルールや、ドキュメントの書き方、定義関数の管理に至るまで
考えなくてはいけない事は多そうです。
従来マクロとの性質の違い、長所短所を理解した上で適用すれば
便利に使えて開発効率が上がる場面もあるのではないでしょうか。

おわり


投稿者:@miya_NI


2010年3月25日木曜日

目的

ユーザ企業がシステムを導入しようとする時、そこにはユーザの目的がある。
開発会社がその仕事を受注する時、そこには会社の目的がある。
複数のメンバーでその開発に携わる時、そこにはチームの目的がある。
そして開発に携わる全ての人に個人の目的がある。

目的に合わせて計画を練り実行に移す時、そこにマネジメントが発生する。
我々は1つ1つの開発に存在する目的をどれくらい理解しているだろうか?
そして目的をより理解するためどれくらい努力をしているだろうか?

2010年3月13日土曜日

ZIP形式で圧縮されたテキストファイルを解凍しないで読み込む方法

NESUG(NorthEast SAS Users Group)のサイトに掲載されていました。

よく読むとundocumentedな機能らしいですが・・・

例えば、temp1.csv~temp3.csvのようなCSVファイルがZIP形式でひとつにまとめられたファイルがあるとします。
↓ ファイル名はtemp_all.zipです。


↓ ZIPファイルの中身はこのような感じです。


↓ 例えば、temp2.csvの中身はこのような感じです。


このtemp_all.zipを解凍しないで圧縮されたままの状態で、その中の1ファイルを読み込む方法です。
(ここでは、temp2.csvを読み込みます)

まず、FILENAMEステートメントでZIPファイルをファイル参照名に定義します。
  filename ファイル参照名 saszipam "ZIPファイルの保存場所" ;
例) filename zipfile saszipam "D:\temp\temp_all.zip" ;

ファイルを読み込むDATAステップのINFILEステートメントではこのように指定します。
  infile ファイル参照名ファイル名 ) ;
例) infile zipfile(temp2.csv) ;
INFILEステートメントのその他オプションは適時指定します。

↓ まとめるとこのような感じです。


↓ 実行結果のログです。

3オブザベーション、3変数のデータセットが作成されたことが確認できます。

↓ 実際にデータを開いてみました。

きちんと読み込めているようですね。



う~ん、ちょっと使いどころがあまり思いつきませんが・・・
いや、いつか役に立つかもしれません!
こんなこともできるんだなぁぐらいの気持ちで覚えておきましょう!


投稿者:@massu_NI


2010年3月8日月曜日

挨拶

朝一番に「おはようございます」としっかり挨拶してみよう。
まるで小学校の朝礼のような内容で恐縮だけれど、マネジメントというものを意識し始 めた時、本を読むよりセミナーに出るよりまずやってみて欲しい。

一緒に仕事をして行く仲間はどんな様子なのか。

体調は良さそうか?やる気がみなぎっている か?悩み事がありそうか?

挨拶をしっかりとすることでいろいろなことが見えてくるはずだ。
まずは一緒に仕事をする仲間としっかりと向き合うこ と、挨拶はマネジメントの重要な第一歩である。

ネイチャーインサイト サイトリニューアル&NIBLOGの引っ越し

ご連絡が遅くなりましたが、 ネイチャーインサイトの際とがリニューアルしました。 https://www.n-insight.co.jp/ それに伴い、NIBLOGも引っ越しすることになりました。 https://www.n-insight.co.jp/niblog/ ...