2018年12月14日金曜日

現地時間などから日本時間を調べたい




海外のなんかのイベントで「ライブ配信がxx時yy分から行われます」って情報があったとき「日本時間だと何時だろう」って知りたい事ありますよね。




例1

直近だと、自宅で使ってる SAS OnDemand for Academics のメンテナンス終了予定が

    Dec 13, 2018 17:00 UTC

みたいに書かれてて、日本時間でいつ終わるのか知りたいってことがあります。ネットで調べれば速攻で分かりますが、SAS使いとしてはSASで調べてみましょう。


data _null_;
   utc_dt = '2018-12-13T17:00:00'dt;
   jpn_dt = tzoneu2s( utc_dt, 'Asia/Tokyo' );
   put jpn_dt= datetime.;
run;

Log
jpn_dt=14DEC18:02:00:00


なるほど、日本時間だと12月14日の2時にメンテが終わるってことですね。

  • 「TZONEU2S関数」は、UTC(世界協定時)を指定したタイムゾーンIDの日時に変換します。
  • ちなみに「SAS timezone id」とかでググれば都市ごとのタイムゾーンIDが載ってるSASのリファレンスが見つかるはずです。
  • 該当する都市のタイムゾーンIDがない場合は、同じタイムゾーンを持つほかの都市を探して設定しましょう(夏時間を導入している都市では、そこも同じかどうか確認するのを忘れずに)



例2

テキサス州ダラスで現地時間2018年12月12日23時10分になんかのライブ配信が行われますってなった時に、日本時間だといつか調べたいとします。

data _null_;
   dal_dt = '2018-12-12T23:10:00'dt;
   utc_dt = tzones2u( dal_dt, 'America/Chicago' );
   jpn_dt = tzoneu2s( utc_dt, 'Asia/Tokyo' );
   put jpn_dt= datetime.;
run;

Log
jpn_dt=13DEC18:14:10:00


日本時間で13日の14時10分からライブ配信が開始だってのが分かります。

  • 「TZONES2U関数」は、指定した日時とそのタイムゾーンIDからUTC(世界協定時)に変換します。
  • ちなみにテキサス州ダラスのタイムゾーンIDがないっぽいので、標準時間と夏時間が同じタイムゾーンを持つ 'America/Chicago' を設定しています。(この同じタイムゾーン調べるのも少し面倒)


関数の区別方法

TZONEU2SとTZONES2Uって似てますが、

・TZONEU2S・・・「UTC datetime to SAS datetime」
・TZONES2U・・・「SAS datetime to UTC datetime」

と考えると覚えやすいと思います。




2018年12月6日木曜日

【PROC MEANS】OUTPUTステートメントでの出力変数の指定方法



PROC MEANS(または PROC SUMMARY)の「OUTPUTステートメント」で統計量をデータセットに出力することが出来ます。


今回は統計量を出力する際の変数の指定方法を紹介したいと思います。




例① 分析変数が1つの場合


proc means data=SASHELP.CLASS;
   var HEIGHT;
   output out=OUT1  min=MIN_HEI  max=MAX_HEI;
run;

または

proc means data=SASHELP.CLASS;
   var HEIGHT;
   output out=OUT2  min( HEIGHT )=MIN_HEI  max( HEIGHT )=MAX_HEI;
run;


・HEIGHTの最小値をMIN_HEI、最大値をMAX_HEIに格納してます。

・基本的に「統計量( 分析変数 ) = 出力変数」という構文ですが、「統計量 = 出力変数」というように分析変数を省略した場合は、VARステートメントに指定した分析変数が使用されます。






例② 分析変数が2つ以上の場合


proc means data=SASHELP.CLASS;
   var HEIGHT WEIGHT;
   output out=OUT3  min = MIN_HEI  MIN_WEI
                              max = MAX_HEI  MAX_WEI;
run;

または

proc means data=SASHELP.CLASS;
   var HEIGHT WEIGHT;
   output out=OUT4  min( HEIGHT WEIGHT ) = MIN_HEI MIN_WEI
                              max( HEIGHT WEIGHT ) = MAX_HEI MAX_WEI;
run;

またはまたは

proc means data=SASHELP.CLASS;
   var HEIGHT WEIGHT;
   output out=OUT5  min( HEIGHT )=MIN_HEI  min( WEIGHT )=MIN_WEI
                              max( HEIGHT )=MAX_HEI  max( WEIGHT )=MAX_WEI;
run;


・HEIGHTとWEIGHTの最小値をそれぞれMIN_HEI、MIN_WEIに格納
・HEIGHTとWEIGHTの最大値をそれぞれMAX_HEI、MAX_WEIに格納




AUTONAMEオプションの利用

proc means data=SASHELP.CLASS;
   var HEIGHT WEIGHT;
   output out=OUT6  min=  max= / autoname;
run;


AUTONAMEオプションをつけると、SASが自動で出力変数名を決めてくれます。
「分析変数名_統計量」という感じの変数名がつけられます。
作成された変数名の長さがSASの制限を超える場合は変数名が切り捨てられるので注意


以下のような書き方も。

proc means data=SASHELP.CLASS;
   var HEIGHT WEIGHT;
   output out=OUT7  min( HEIGHT )= / autoname;
run;




ちなみに指定出来る統計量は、、
  統計量   内容
  N   N
  NMISS  欠損値の数 
  SUM  合計
  MEAN  平均値
  MIN  最小値
  MEDIAN   中央値
  MAX   最大値   
  RANGE  範囲
  MODE  最頻値   
  STDDEV  標準偏差   
  STDERR  標準誤差   
  Q1  下側四分位点 
  Q3  上側四分位点  
  QRANGE  四分位範囲  
  KURT  尖度
  SKEW  歪度
  …etc

など、その他豊富に取り揃えています。詳細はリファレンスを参照ください。




2018年12月5日水曜日

【PROC UNIVARIATE】OUTPUTステートメントでの出力変数の指定方法




PROC UNIVARIATE の「OUTPUTステートメント」で統計量をデータセットに出力することが出来ますが、「統計量を出力する際の変数の指定方法がよく分からない!」って方がいたので、まとめておきます。




例① 分析変数が1つの場合

proc univariate data=SASHELP.CLASS noprint;
   var HEIGHT;
   output out=OUT1  min=MIN_HEI  max=MAX_HEI;
run;

・分析変数HEIGHTの最小値をMIN_HEI、最大値をMAX_HEIに格納してます。




例② 分析変数が2つ以上の場合

proc univariate data=SASHELP.CLASS noprint;
   var HEIGHT WEIGHT;
   output out=OUT2  min=MIN_HEI  MIN_WEI
                               max=MAX_HEI  MAX_WEI;
run;

または

proc univariate data=SASHELP.CLASS noprint;
   var HEIGHT WEIGHT;
   output out=OUT3  min=MIN_HEI  min=MIN_WEI
                               max=MAX_HEI  max=MAX_WEI;
run;



・分析変数HEIGHTとWEIGHTの最小値をそれぞれMIN_HEI、MIN_WEIに格納
・分析変数HEIGHTとWEIGHTの最大値をそれぞれMAX_HEI、MAX_WEIに格納



ちなみに指定出来る統計量は、、
  統計量   内容
  N   N
  NMISS  欠損値の数 
  SUM  合計
  MEAN  平均値
  MIN  最小値
  MEDIAN   中央値
  MAX   最大値   
  RANGE  範囲
  MODE  最頻値   
  STDDEV  標準偏差   
  STDERR  標準誤差   
  Q1  下側四分位点 
  Q3  上側四分位点  
  QRANGE  四分位範囲  
  KURT  尖度
  SKEW  歪度
  …etc

その他あわせて40~50個程度の統計量を豊富に取り揃えています。詳細はリファレンスを参照ください。


2018年11月28日水曜日

コンパイルしたマクロを削除する





マクロを削除する方法1

%SYSMACDELETE  マクロ名 ;

  • 「WORK.SASMACR」内にあるマクロを削除することが出来ます
  • サイドセッションを使用するアプリケーションやプログラムでは、マクロが「WORK.SASMACn」(nは一意の整数)に格納されるため、該当セッションの「WORK.SASMACn」内のマクロが削除対象になる


例
%sysmacdelete test1;






マクロを削除する方法2

PROC CATALOG  CAT=ライブラリ名.カタログ名  ET=MACRO;
     DELETE  マクロ名1  マクロ名2 ・・・ ;
RUN;
QUIT;

  • 対象のライブラリとカタログ名を指定することが出来ます。
  • 削除したいマクロ名を列挙します。


例
proc catalog cat=mymac.sasmacr et=macro;
   delete test1 test2 test3;
run;
quit;






マクロを削除する方法3  (注意事項あり)

PROC CATALOG  CAT=ライブラリ名.カタログ名  KILL FORCE;
RUN;
QUIT;

  • カタログ内の「全エントリー」を削除します。
  • 「全エントリー」とはマクロだけでなくフォーマットなどのあらゆるエントリーを含みます。
  • 「KILL」オプションは PROC CATALOG 内の他のオプションやステートメントより先に動作します。たとえばDELETEステートメントで削除するマクロを指定していても意味はなく、カタログ内の全エントリーを削除してしまいます。


2018年11月22日木曜日

FIRSTOBS=, OBS=, WHERE を組み合わせたときの挙動




データセットオプション「FIRSTOBS=」と「OBS=」の紹介と、WHEREステートメントを組み合わせて使用した時の挙動について、まとめておきます。



データの状態によっては結果がバグる事があって、その辺の注意点については最後に別記事のリンク貼ってるので参照下さい。



Sample data
data a;
   do i=1 to 10;
     output;
   end;
run;





FIRSTOBS=オプション

・処理(読込み)を開始するオブザベーションを指定できます。

proc print data=a (firstobs=3);
run;




OBS=オプション

・何オブザベーション目まで処理するか(読み込むか)を指定できます。

proc print data=a (obs=3);
run;




FIRSTOBS=, OBS=, WHERE の組み合わせ

ここから本題。以下のプログラムで結果が予測できればバッチリです。

proc print data=a (firstobs=2 obs=3);
  where i>5;
run;


解説
・まずWHEREでオブザベーションを抽出。
・抽出したオブザベーションに対して、FIRSTOBS=とOBS=を適用。
・FISTOBS=とOBS=で共通する範囲にあるオブザベーションが処理対象となる。


以下にイメージを載せておきます。


ちなみに

SETステートメントとかでもこれらのオプションが使えます。

data b;
  set a (obs=3);
run;



注意


以下の記事で、FISTOBS=オプション自体の落とし穴も紹介しています。
FIRSTOBSオプションの落とし穴




2018年11月20日火曜日

FORMATの落とし穴【デフォルト長】




PROC FORMAT の VALUEステートメントでありがちな落とし穴。
以下のプログラムと結果をご覧ください。結果は想定通りでしょうか?

proc format;
   value $FMT
       "a"    = "x"
       "abc" = "y"
   ;
run;

data DT1;
   format VAR1 $FMT.;
   VAR1 = "abc";
run;

  VAR1  
  x 

変数VAR1は "abc" なのでフォーマット$FMTを貼りつけると "y" と表示されるはずが、 "x" が表示されてしまいました。



原因

これは「デフォルト長 (Default Length)」というものが関係してます。
例えば、今回の例で

proc format;
   value $FMT
       "a"    = "x"
       "abc" = "y"
   ;
run;


等号の右側に定義した値 ("x" と "y") の文字の長さは1バイトです。
この長さが、そのフォーマットの「デフォルト長」というものになります。
(定義した値が複数ある場合は、右側の文字の長さが最も大きいものがそのフォーマットの「デフォルト長」になる)



そしてこのフォーマット$FMTは、以降のFORMATステートメントでデフォルト長となった1バイトしか視界に入らなくなります。
どういう事かというと、、

data DT1;
   format VAR1 $FMT.;
   VAR1 = "abc";
run;

変数VAR1 の値 "abc" から先頭の1バイトの値 "a" だけを見て対応するフォーマット値を表示しようとします。



ちょうど PROC FORMAT で "a" = "x" と定義してたので、この値が表示されちゃったというわけですね。

proc format;
   value $FMT
       "a"    = "x"
       "abc" = "y"
   ;
run;


ちなみに...

以下のように、PROC FORMATから1つ目の「"a" = "x"」をコメントアウトして定義から外すと、、、

proc format;
   value $FMT
/*       "a"    = "x" */
       "abc" = "y"
   ;
run;

data DT1;
   format VAR1 $FMT.;
   VAR1 = "abc";
run;

  VAR1  
  a 

まずは変数VAR1 の値 "abc" から先頭の1バイトの値 "a" だけを見て対応するフォーマット値を表示しようとしますが、
対応するフォーマットがないので、そのままの値 "a" が表示されちゃってるわけですね。
この辺の挙動を知らないと「なんじゃこりゃ??」となってしまいますね。



解決策

変数VAR1 の値 "abc" の文字の長さは3バイトなので、3バイト全部読み込んで表示する必要があります。
解決策としては以下の2つの方法があります。


解決策①
proc format;
   value $FMT (default=10)
       "a"    = "x"
       "abc" = "y"
   ;
run;

data DT1;
   format VAR1 $FMT.;
   VAR1 = "abc";
run;

  VAR1  
  y 

「DEFAULT=オプション」によってこのフォーマットのデフォルト長を 10 に広げています。


解決策②
proc format;
   value $FMT (max=10)
       "a"    = "x"
       "abc" = "y"
   ;
run;

data DT1;
   format VAR1 $FMT10.;
   VAR1 = "abc";
run;

  VAR1  
  y 

「format VAR1 $FMT10.」として、FORMATステートメントで、フォーマット名の後ろに幅を指定することも出来ます。
今回は幅を10に設定して問題なく動作していますが、「出力形式〇〇に指定した幅は無効です」みたいなERRORが出る事があります。そういった場合はFORMATプロシジャで「value $FMT (max=10)」というように、指定可能な幅の最大値を設定する必要があります。




See also

インフォーマットでも同様の落とし穴があります。
INFORMATの落とし穴【デフォルト長】


ポイント
・文字値から数値に変換するINVALUEステートメントでは「左側」に定義した文字の長さがデフォルト長になる
・VALUEステートメントでは「右側」に定義した文字の長さがデフォルト長になる


2018年11月1日木曜日

SQLビューは同じ変数名が複数あってもエラーにならない




SQLビューの落とし穴です。以下をご覧ください。

proc sql;
   create view myview as
   select  name,
              111 as var1,
              222 as var1
   from  sashelp.class;
quit;


proc print data=myview noobs;
run;


なにこれ、VAR1が2つ存在しちゃってる、エラーにもなってない。。
実はCREATE VIEWでは、同じ名前の変数がいくつも存在する状態を作り出すことが出来てしまうんです。



では、先ほどのSQLビューに対して、VAR1を選択してPROC PRINTすると、、

proc print data=myview noobs;
   var var1;
run;


1個目のVAR1がプリントされました。2個目はどうした。



私自身、この挙動を知らずにミスったことがあります。
その時の状況として、変数が数十個あるデータセットに対して、

select  *, x+y as var1

みたいなselect文を書いたSQLビューを作りました。ですが元々データセットにVAR1っていう変数が存在していて、それを知らずにSQLビューの中でもVAR1っていう変数を作ってしまっていました。

このSQLビュー内で作ったVAR1に対して、

proc means data=○○;
   var var1;
run;

みたいな事をやろうとしたところ、元々データセットに存在しているVAR1に対して集計が行なわれてしまい、結果がおかしい!?ってなりました。



See also...
SQLビューの作成と落とし穴①