filenameで複数ファイルを一括指定して、読み込む場合に各ファイル1行目がラベル行だと、難しいことになるがeovをうまく使えば解決できる話

まずはSAS忘備録の記事「外部ファイルをいっぺんに読み込んで連結する。」を読んで
ください。
http://sas-boubi.blogspot.jp/2014/06/blog-post.html

そこで、以下のようなファイルが、1つのフォルダの中に入ってるとします。

 

(カーソルで潰れてますが 1行目はX Y Zって入ってます)

なんだ、忘備録の方法で一発じゃんと思い


とりあえず、1つにfilenameします。

filename in "C:\temp\TEST\*.txt";

なおSAS雲丹の場合は、既定のフォルダ内に作成してから、
filename in "/folders/myfolders/TEST/*.txt"; とかですね。



data A1;
infile in;
input X Y Z $;
run;

とします。するとなんだかログに

NOTE: X に対して、無効なデータが行 1 カラム 1-1 にあります。
 NOTE: Y に対して、無効なデータが行 1 カラム 3-3 にあります。
 NOTE: X に対して、無効なデータが行 4 カラム 1-1 にあります。
 NOTE: Y に対して、無効なデータが行 4 カラム 3-3 にあります。
 NOTE: X に対して、無効なデータが行 7 カラム 1-1 にあります。
 NOTE: Y に対して、無効なデータが行 7 カラム 3-3 にあります。」

いっぱいでます。
は?NOTEなんて出てても問題ないでしょ。しらねぇよ。と思ってデータセットを開けると

















おぉ?なんだこれ。ってなります。

ああ、そうか忘備録の例ではテキストの1行目からデータだったけど、
今回は1行目はラベルがはいってんのか、これはデータじゃないからな。
数値型の変数にラベルの文字列を入れようとしたからNOTEがでて、欠損値になってんのか。
はいはいはい、よし!

data A2;
infile in firstobs=2;
input X Y Z $;
run;
















firstobs=2として、2行目から読み込めば問題なし!
楽勝!
…なんかやっぱりログにNOTEでてるけど無視無視!
と思って、データセットを開けると

おぉ。そうじゃないよって感じですね。
しかし、filenameの一括指定は、複数のファイルを1つのファイルとして擬似的に
みなして処理するのでfirstobs=2などとしても、1番最初のファイルの1レコード目以外
は読み込まれてしまいます。

さて、この各ファイルの先頭行を読まずに、ファイル一括指定で
データセットをどう作るかという問題、どう攻めますか?

まあ、個別に1ファイルずつ読み込んで、データセットを後で縦結合でもいいですけど
そんなことする必要はありません。

盤上この一手は「eov」オプションの活用です。
eovとは何か、それは、複数ファイルからの読み込み時に
2ファイル目以降の先頭に1をたてるオプションです。
ただ、いきなり何もせずに指定すると、2ファイル目の先頭で
1が立って以降、1がretainされる性質を持っているので、
各レコードの読み込み前に0にもどす必要があります。

以下のコードはeovの働きをみるサンプルです。

data A3;
infile in eov=eov;
eov = 0 ;
input X Y Z $;
FL = eov;
N =_N_;
run;

結果は以下のようになります。

















さて、そのeovの働きを活かして、今回やりたいことを実現するコードは

以下の通りです

data A4;
infile in eov=eov;
eov = 0 ;
input @;
if _N_ ^= 1 and eov ^= 1 then do;
input X Y Z $;
output;
end;
run;













なるほど、_N_ = 1は1ファイル目の1レコード目、eov=1は2ファイル目
以降の1レコード目だから、それ以外の時にinputするわけか。

けど、「input @;」は何?
これは、実はeovに1が入るのはinput文が実行された時なんですね、
しかし今回は余計なNOTEを出さないためにも
input文を実行するかどうかを条件分岐したいわけで、読み込んで
からじゃ遅いわけですね。
ので inputの後に変数名を指定せずに、空撃ちしているわけです。
@はつけないと、読み込みが次の行にいってしまいます(ポインタが移動。@をつけるとその行に留まる)。
空撃ちした後、読み込むかどうかの結果がでるまでその場で足踏みしとけってことですね。

以上、おそまつ。


0 件のコメント:

コメントを投稿