ラベル ステートメント: LIBNAME の投稿を表示しています。 すべての投稿を表示
ラベル ステートメント: LIBNAME の投稿を表示しています。 すべての投稿を表示

2017年1月27日金曜日

【SAS入門】データセットを保存する。





ライブラリ参照



SASには「ライブラリ参照」という考えがあります。以下の例をご覧ください。

 libname  MYLIB "C:\TEST";

フォルダパス「C:\TEST」の中を、「MYLIB」という名前で参照できるようにしています。
この参照の事を「ライブラリ参照」といいます。



構文
LIBNAME  適当な参照名  "フォルダのパス";




データセットの保存


このライブラリ参照「MYLIB」にデータセットを保存するには、以下のように書きます。

data MYLIB.OUT1;
   ~ 適当なデータステップ ~;
run;

MYLIB(つまりC:\TESTの中)にOUT1というデータセット名で保存しています。





保存したデータセットの参照


保存したデータセットを以下のような感じで参照できます。

* 例1 ;
data DT2;
   set MYLIB.OUT1;
run;


* 例2 ;
proc print data=MYLIB.OUT1;
run;




補足


参照名を省略した場合、たとえば以下のような場合、、

data DT1;
   A=1;
run;


内部で以下のように置き換えて実行されます。

data WORK.DT1;
   A=1;
run;


ライブラリ参照「WORK」は、SASが勝手につくるライブラリです。
WORKはSAS終了時に削除されます。

なので、一時ファイルを格納する場所になります。


ただし、この補足で説明した挙動は、「USER」という特殊なライブラリを定義すると変わってしまうので注意。
(あまり使われない&知られていない機能なので説明は割愛します)



2016年10月12日水曜日

「LIBNAME ACCESS=READONLY」で読み取り専用ライブラリにする。


今日身近な人から 「データセットが上書きできない!なんでや!」 って質問いただきました。


答えは簡単で、以下のようにLIBNAMEステートメントに「ACCESS=READONLY」が設定されていたため、読み取り専用のライブラリ参照になっていたのが原因でした。


libname MYLIB "C:\TEST" access=readonly;

data MYLIB.DT1;
   set SASHELP.CLASS;
run;

ログ
ERROR: メンバーMYLIB.DT1.DATAへの書込みアクセスは拒否されました。



質問いただいた人は無事すぐに解決となりました。
私自身もそうですが、結構こういう簡単な部分に気付かず何十分無駄にするってことありますよね。

2015年7月31日金曜日

割り当てられたライブラリまたはファイル参照をログに出力する。


以下のプログラムで、全ての参照名と参照パスがログに出力されます。


ライブラリの確認
  libname _all_  list;



ファイル参照の確認
  filename _all_  list;



システム用の参照も出てきます。

2015年2月9日月曜日

EXCELを読み込む方法と落とし穴 【LIBNAME EXCEL編】



Windows環境での機能で、SAS/ACCESSのライセンスも必要ですが、LIBNAMEでEXCELを読み込めます。
えぐい落とし穴もあるので最後までご覧ください。


以下のEXCELファイルを読み込みたいとします。

C:\test.xlsx
















データ部分のセル書式は「A列: 標準」「B列: 標準」「C列: 日付」「D列: 時刻」としています。







*** 正しく読み込めないので注意 ******;
* libnameで、EXCELファイルを参照する ;
libname TEST excel "C:\test.xlsx"
                header = yes
                dbmax_text = 8000
                scan_timetype = yes
                mixed = yes ;

* SET ;
data OUT1;
   set TEST."Sheet1$"n;
run;

* EXCELファイルを解放 ;
libname TEST clear;

OUT1
 
  B  
 C 
 D 
   1
  1
                 .
           .
   2
  1
 10JAN2012 
 10:20:00
   3
  1
                 .
           .
   4
  1
                 .
           .
   5
  
                 .
           .
   6
  
 20OCT2012
           .
   7
  1 
                 .
           .
   8
  1 
                 .
           .
   9
      
                 .
           .

黄色で示した部分は「aaa」という文字が読み込まれるはずだけど、欠損値になってしまう事に注目。



解説

libname TEST excel "C:\test.xlsx"
                header = yes
                dbmax_text = 8000
                scan_timetype = yes
                mixed = yes ;

LIBNAMEでEXCELファイルを参照出来るようにしています。
以下が構文(オプションは一部抜粋)

libname  参照名  excel  "EXCELファイルのフルパス"
   header             = yes | no  … 読み込み範囲の最初の行を変数名として読み込むか 
   dbmax_text      = 数値      … 文字変数の最大LENGTHを指定
   scan_timetype  = yes | no  … 項目のデータ型が時刻かどうかスキャンして取り込むか
   mixed              = yes | no  … 1つの項目に数値と文字が混在してたら、文字変数として取り込むか
;

data OUT1;
   set TEST."Sheet1$"n;
run;

EXCELの中身を、「参照名."EXCELシート名$"n」という感じで参照できます。


libname TEST clear;

最後にEXCELファイルを解放。




落とし穴(環境により動作は異なる)


実は、LIBNAME EXCELでの読み込みでは、EXCELのデータ部分の先頭8行だけを調べて、データ型などの属性が決定されているようです。
(レジストリの設定とか、環境によっては異なる可能性あり)

この「先頭8行ルール」により以下①~③の読み込み失敗例が考えられます。



① mixed=yesのオプションをつけると、数値と文字が混在してる項目を、文字変数にしてくれるのですが、、、

「先頭8行ルール」により、先頭8行に数値しかない場合、数値変数と判断されます。
そこで、もし9行目以降に文字があると、そこが取り込めず、欠損値になってしまいます。



黄色セルが、欠損値になってしまうやつ。











② 「先頭8行ルール」により、以下のように先頭8行が全て255バイト以内の文字で、9行目以降に256バイト以上の文字がある場合、256バイト以降の文字が切れたり、「?」とか変な文字になる。




黄色セルが、変になるやつ。















③ 「先頭8行ルール」により、以下のように先頭8行の書式が「標準」や「数値」で数値のみが入力されていると数値変数と判断されて、9行目以降に書式が「時刻」や「日付」で時刻(または日付)が入力されていると、9行目以降の当該データはEXCELのシリアル値で読み込まれてしまいます。



「10:20」の場合は「0.430555・・・」というシリアル値で読み込まれる。










ここまでが「先頭8行ルール」による落とし穴で、他にも以下のような落とし穴がある。

④ これもかなり特定の条件ですが、以下のように数値と256バイト以上の文字のみで構成されてるデータで、書式が「標準」や「数値」になってる場合、数値変数と判断されて、文字はすべて欠損値になってしまう。



黄色セルが、欠損値になってしまうやつ。










⑤ オプションの設定によって挙動が変わりますが、今回紹介したプログラムの設定のまま以下のEXCEL (データ部分の書式は「A列: 日付」「B列: 時刻」「C列: ユーザー定義[yyyy/m/d h:mm]」) を読み込むと、、









変数Cが日付値として読み込まれてしまいました。
  B  
 C 
 01JAN2012 
 12:28:00 
 01FEB2012
 02JAN2012
 13:00:00
 02FEB2012 



一応、以下の青文字で示した「SASDATEFMT=」というオプションに、対応させたいフォーマットを指定すると日時として読み込めるようです。
libname TEST excel "C:\test.xlsx"
                header = yes
                dbmax_text = 8000
                scan_timetype = yes
                mixed = yes ;

data OUT1;

   set TEST."Sheet1$"n (sasdatefmt=(C=datetime19.));
run;



⑥ データステップ等でLIBNAME EXCELのファイルにアクセスする際、WHEREステートメントは使わない方が良さそう。
というのも、変数に欠損値があるとWHEREステートメントでうまくオブザベーションが抽出できない場合がありました。SAS社のリファレンスからはこの辺の説明が見つけられなかったので、環境によるものかも不明です。

data OUT1;
   set TEST."Sheet1$"n;
   where B^=1;   /* ← NG */
run;




以上、わたしが気づいた範囲のえぐい落とし穴でした。

実は根本的な解決法が無いのが現状です。
一応自分なりに、こうするしかないかなぁー。。という方法はあるので、記事としてまとめられたら紹介したいと思います。

追記
いろいろ調べた結果、次回紹介予定の方法で正しく動く確証がもてなかったので、他にいい方法がないか、引き続き調査したいと思います。

この方法を使う際は、動作環境によってうまく動かないことがあったり、EXCELの仕様など不確定要素があったりなので、想定通りに読み込めているかを確認した方が良さそうです。



2014年11月28日金曜日

LIBNAMEを使わずに永久データセットを取り扱う小技



LIBMAMEを使わずに、永久データセットを扱う方法があります。


以下は パス「C:\TEST」 の中にDT1というデータセットがあったとして、それをWORKにSETする例です。

libname MYLIB "C:\TEST";

data DT1;
   set MYLIB.DT1;
run;

これが普通の書き方ですが、
実は以下のように、フルパスを指定することも出来ちゃいます。

data DT1;
   set "C:\TEST\DT1";
run;


一時的な作業であれば素早く書けて便利です。
がっつりプログラムを書く場合は、libnameでパスを通す基本的な書き方のほうが、プログラムとしてはキレイなのでそっちを使うほうがいいかと思います。



2014年10月1日水曜日

ライブラリをいっぺんに割り当てる方法




ライブラリをいっぺんに取り消す方法とは逆に、いっぺんに割り当てる方法を紹介。


たとえば、「C:\TEST」というパスに 「A」「B」「C」というフォルダがあったとします。
これらにライブラリを割り当てたいとします。



① LIBNAMEステートメント


ライブラリを割り当てる構文
LIBNAME ライブラリ参照名 "割り当てるパス";

* ライブラリを割り当て ;
libname mylib1 "C:\TEST\A";
libname mylib2 "C:\TEST\B";
libname mylib3 "C:\TEST\C";



② LIBNAME関数


データステップ内でもLIBNAME関数でライブラリの割り当てが出来ます。


ライブラリを割り当てる構文
リターンコードを格納する変数 = LIBNAME( "ライブラリ参照名", "割り当てるパス" );

    • 割り当てが成功したか失敗したか、などの情報はログに表示してくれません。
    • その代わり、LIBNAME関数のリターンコードには以下が格納される。
      • 割り当てが成功した場合「0」
      • なんらかのERROR、WARNING、NOTEなど特記事項がある場合は「0以外」(特記事項はSYSMSGという関数で取得できる)


    * ライブラリを割り当てる ;
    data _null_;
            length msg $2000.;

            rc = libname( "mylib1", "C:\TEST\A" );
            if rc^=0 then do;
               msg=sysmsg();
               put msg;
            end;
            rc = libname( "mylib2", "C:\TEST\B" );
            if rc^=0 then do;
               msg=sysmsg();
               put msg;
            end;
            rc = libname( "mylib3", "C:\TEST\C" );
            if rc^=0 then do;
               msg=sysmsg();
               put msg;
            end;
    run;



    以下のようにDOループなどを使っていっぺんに割り当てたり、色々工夫の余地があります。

    * ライブラリを割り当てる ;
    data _null_;
          length x msg $2000.;
          do  x = "A", "B", "C";
               i + 1;
               rc = libname( cats( "mylib", i ) , cats( "C:\TEST\", x ) );
               if rc^=0 then do;
                   msg=sysmsg();
                   put msg;
               end;
          end;
    run;




    2014年8月25日月曜日

    ライブラリをいっぺんに取り消す方法



    1つまたはすべてのライブラリを取り消す方法を紹介します。



    ① LIBNAMEステートメント


    ライブラリを取り消す構文
    LIBNAME ライブラリ参照名 CLEAR;

      すべてのライブラリを取り消す構文
      LIBNAME _ALL_ CLEAR;


        * 適当にライブラリを割り当て ;
        libname test1 "適当なパス1";
        libname test2 "適当なパス2";

        * ライブラリ「TEST2」のみ取り消す ;
        libname test2 clear;




        ② LIBNAME関数


        データステップ内でもLIBNAME関数でライブラリの取り消しが出来ます。


        ライブラリを取り消す構文
        リターンコードを格納する変数 = LIBNAME( "ライブラリ参照名" );

          • 取り消しが成功したか失敗したか、などの情報はログに表示してくれません。
          • その代わり、LIBNAME関数のリターンコードには以下が格納される。
            • 取り消せた場合「0」
            • なんらかのERROR、WARNINGなど特記事項がある場合は「0以外」(特記事項はSYSMSGという関数で取得できる)


          * 適当にライブラリを割り当て ;
          libname test1 "適当なパス1";
          libname test2 "適当なパス2";

          * ライブラリ「TEST1」「TEST2」を取り消す ;
          data _null_;
                  length msg $2000.;

                  rc = libname( "test1" );
                  if rc^=0 then do;
                     msg=sysmsg();
                     put msg;
                  end;

                  rc = libname( "test2" );
                  if rc^=0 then do;
                     msg=sysmsg();
                     put msg;
                  end;
          run;



          以下のようにDOループなどを使ってドカッと取り消したり、色々工夫の余地があります。

          * 適当にライブラリを割り当て ;
          libname test1 "適当なパス1";
          libname test2 "適当なパス2";
          libname test3 "適当なパス3";

          * ライブラリ「TEST1」~「TEST3」を取り消し ;
          data _null_;
                length msg $2000.;
                do i = 1 to 3;
                     rc = libname( cats( "test", i ) );
                     if rc^=0 then do;
                         msg=sysmsg();
                         put msg;
                     end;
                end;
          run;

          上の例を簡単に説明しておくと、
          • DOループで変数 i の値を1~3まで変化させながら、
          • CATS関数で "test" という文字と変数 i の値を結合します。
          • その結合した文字が表すライブラリ参照をLIBNAME関数で取り消しています。