2018年6月15日金曜日

call is8601_convertルーチンの話

is8601_convertコールルーチンは,日付や2つの日付の間の間隔をiso8601フォーマットに変換します.
この日付の間隔のことを,デュレーション値と呼ぶようです.
たとえば始点が4月1日,終点が4月2日のとき,デュレーション値は1日です.
第一引数に変換前の値に何が入るかを指定し,第二引数に変換後の値が何であるかを指定します.
第三引数に変換前の値,第四引数に変換に使う値,第五引数に変換後の値を格納する変数を指定します.

第一引数に'du/dt'と指定すると,第三引数にデュレーション値,第四引数に日付を指定します.
これが逆になるとエラーが返ります.
同様に'dt/du'と指定すると,日付→デュレーション値の順に指定をしないといけません.

とてつもなくわかりにくいので以下にいくつか具体例を示します.

data _null_ ;
  format hoge e8601dn. ;
  /*変換前の値はデュレーション値と日付,変換後に期間の開始日を出力,期間は8週間,期間の終点は2018年1月1日*/
  call is8601_convert('du/dt' , 'start' ,"p8w" ,"2018-01-01" ,  hoge ) ;
  putlog hoge = ;
run ;

hoge=2017-11-06


data _null_ ;
  format hoge e8601dn. ;
  /*変換前の値は日付とデュレーション値,変換後に期間の終了日を出力,期間の開始日は2018年1月30日,期間は8週間*/
  call is8601_convert('dt/du' , 'end' ,"2018-01-30" ,"p8w" , hoge ) ;
putlog hoge = ;
run ;

hoge=2018-03-27


data _null_ ;
  length hoge $20 ;
  format hoge $n861b. ;
  /*変換前の値に日付と日付,変換後はデュレーション値,期間の始点は1月30日,終点は3月14日*/
  call is8601_convert('dt/dt' , 'du' ,"2018-01-30T12:30" ,"2018-03-14T14:45" , hoge ) ;
  putlog hoge = ;
run ;

hoge=P1M15DT2H15M

2018年5月23日水曜日

ods rtfでのファイル名の上限の話

何やら身辺が立て込んで仕方がないです.

ods rtfではパス名とファイル名の合計文字数は180文字が上限のようですね.
windows上の制限は256文字なので,上限いっぱい使ってもまだ余裕があるみたいですが.

ただパス名込の文字数なので,76文字以上のフォルダに移動するとwindowsでの制限に引っかかりますね

180文字を超えた名前を指定すると,
無効なファイル名です,致命的なODSエラーが発生しました.のerrorが返ります.


2018年4月9日月曜日

putlogでlogに任意の値を出力する話

putlogをご存知でしょうか.logに任意の文字列を出力するステートメントです.

これを使ってデータの中のイレギュラーデータを(ある程度)見つけようと言う試みです.
ためしに下のデータセットがあるとして,変数aには欠測は本来入らないと仮定してください.
その変数aに欠測が入ってるかどうかと,欠測の時のほかの変数の値をlogに出力するのが以下のプログラムです.
私は最近知っていたく感動したのですが,普通にご存知の方が多いのでしょうかね...?

putlogで指定した変数の値が出力できるので,それを利用した形になります.
自分で指定した条件に該当するレコードがなかった場合,logには何も出てきません.

"E" "RROR"とputlogに指定しているのは,ログには"ERROR"と出したいが,
ログに出す条件のレコードが何もないときはERRORとログに残したくないためです.
涙ぐましいですね.この小細工が.

/*---------- ここからプログラム ----------*/

data hoge ;
 a = 1 ; b = 1 ; c = 6 ; output ;
 a = 1 ; b = 2 ; c = 5 ; output ;
 a = . ; b = 3 ; c = 4 ; output ;
 a = 1 ; b = 4 ; c = 3 ; output ;
 a = . ; b = 5 ; c = 2 ; output ;
 a = 1 ; b = 6 ; c = 1 ; output ;
run ;

data _null_ ;
  set hoge ;

 /* -- 想定の値以外(今回は欠測)があるときにlogに出力 -- */
  if a = . then do ;
    putlog "E" "RROR_A" ;
    putlog b = c = ;
  end ;

run ;


2018年4月4日水曜日

ルール間違ってた

「pandemic」というボードゲームにリベンジしてきました.
致命的なルールの勘違いをしていたことに気づいてしまいました.
4戦全敗した後でですが...
規則の確認を雰囲気でやってはいけない好例です.

このゲーム,ワクチンを作って病原菌を根絶(盤上から赤青黒黄の四色の駒を完全に取り除くこと)したら勝ちだと思っていたのですが,ワクチンを4種作った段階で勝ちなのですね.そら勝てないね.

ワクチンは一枚目の画像の版下部にある,なんか四角い四色の駒ですね.
一枚目の画像は赤のワクチン駒を獲得する前に時間切れで負けです.















2枚目は一応勝ちの状態です.盤下部に赤青黄黒の四角いワクチン駒を獲得できています.
しかしこれは参考程度です...手放しで喜べない勝ちなのです...
本来ランダムに決まるプレイヤの役職を,事前に選んでプレイしましたからね...
普通に勝利は次回に持ち越しですね...


2018年3月3日土曜日

グラフのラベルに改行を入れる話

SASでグラフを出す時に,軸のラベルや軸目盛の値の改行をするにはannotateをするしかない,と思っていました.
ところがどっこいaxisステートメントの指定の仕方で改行できるようです.
軸ラベルを改行させてほしいとリクエストが来るたびに,相手のことを呪っていたわけですが
これからはそんな呪いからも解放されますね.

sgplotで軸目盛のラベルの改行は出来たのですが,軸そのものへのラベルの改行のやり方が分からないのが次なる課題ですね...

/*---------- testデータ ----------*/

data hoge;
    call streaminit(11);
    do A=1 to 5;
        Y = int(rand('uniform') *10 );
        output;
    end;
run;

*---------- gplotでの場合 ;
proc gplot data = hoge;
    plot Y * A / vaxis = axis1 haxis = axis2 ;
    symbol1 c = black V = dot I = join;

    *---------- y軸目盛;
    axis1
      order = (0 to 5 by 1)
      origin=(10, 30)
      ;

    *---------- x軸目盛;
    axis2
      order=( 1 to 5 by 1 )
      origin=(10, 30)
      label=("x軸" j = c "ラベル")
      value=(tick = 1 "1" j = c "時間" j=c "経過"
             tick = 2 "2" j = c "時間" j=c "経過"
             tick = 3 "3" j = c "時間" j=c "経過"
             tick = 4 "4" j = c "時間" j=c "経過"
             tick = 5 "5" j = c "時間" j=c "経過"
            )
    ;
 run;

gplotでの出力イメージ












*---------- sgplotでの場合 ;
proc sgplot data = hoge  ;
    series x = A y = Y  ;

    xaxis
      type  = discrete
      fitpolicy=splitalways
      splitchar="*"
      label="x軸ラベル"
      values=(1 2 3 4 5)
      valuesdisplay=("1*時間*経過" "2*時間*経過" "3*時間*経過" "4*時間*経過" "5*時間*経過")
    ;   
run ;

sgplotでの出力イメージ

2018年2月19日月曜日

勝利を知りたい

この記事はsas関係ないです.ボードゲームです.

私趣味でボードゲームをたまにやるのですが,こないだぼこぼこに負けました.
「パンデミック」というプレイヤで協力して目的を達成するゲームがあるのですが,
そこでまあ見事に2戦2敗キメましたのでその供養です.

4人のプレイヤで協力して世界に蔓延る 4種類の病原菌を根絶することを目指すゲームです.詳しくは適当に調べてください.
私はそこで「ほかのプレイヤを動かせる」という固有の能力を持っていたのですが,あまり活用できませんでしたね…指定した離れた土地にプレイヤを一人ワープさせる力をもっと使いこなせていれば敗北とは違った結果が得られたかもしれません.

次やったときは確実に病原菌を根絶してくれよう覚悟してろ


敗北の盤面がこちら

2018年2月14日水曜日

割り算に欠測とか0が混ざってる時の話

割り算する時に,分子が0の時や分母が0とか欠測の時はどうなりますか,と聞かれました.

割った結果は何となくわかるのですが,logになんと出力されるのかが分からなかったので
実際に実行してlogを見たと言うだけの話です.

data DATA ;
    a = 1 ; b = 2 ; output ;
    a = 0 ; b = 2 ; output ;
    a = 1 ; b = 0 ; output ;
    a = . ; b = 2 ; output ;
    a = 1 ; b = . ; output ;
run ;

data DIVISION ;
    set DATA ;
    c = a / b ;
run ;


実行log





結果















分母が0の時は,0による割り算がありましたってnoteが出ていますね.
欠測がどっちかに入っている時は,欠測値を含んだ計算により...と言うよく見るやつが出ています.
その下の以下の箇所で演算式を計算できなかった...と言うのは0による割り算に対して出ています.
分子が0で分母に数が入っている場合は,結果が0として出ます.