2024年11月1日金曜日

SASの勉強会に行ってきた話

 先日sasの棒発表会に参加した。偉大な主催者の人徳により今回も盛況に終わった。午後の間に発表を21本聞くのは本当に疲れた…

一番興味深いのはSASPACに関する発表。SASは作ったマクロなどを公開するには、ブログなりにコードを記載するくらいしかなかったのが、SASPACを使えば統一されたformatで公開できるというわけだ。あまりにも便利そう。そんな場所に公開できるほどの立派な代物をひとつも持っていないことが大きな問題か…

私も発表…はしたのだが、勉強会公式で資料が公開されているし、身バレが怖いのでここでは資料の公開はしない。身バレコワイ。今年も無事開催になり、私に発表の機会を与えてくれた運営の皆様には感謝の限り。来年のネタないんだがどうしよう…

2024年10月14日月曜日

sasユーザー会2024に参加した話

 なんだか数年ぶりにユーザー会に参加した。今年の会場も東大だったがキャンパスが違うとのこと。まあ何となく人の流れに乗っていくと無事ついたので良かった。自分の発表が一日目の午前であることに気が付いたのが当日3日前とかだったので、諸々の申請が間に合わず頑張って朝7時前の新幹線に乗って会場に突入。前泊…したかったな…。現地ではまさかトラック3がトラック2より大きい会場とは思わず、随分会場付近をトラック3の場所を求めてノベルティでもらったsasエナジードリンクを片手にウロウロとしてしまったのはご愛嬌。多分かなり怪しい人物になっていたと思う。…sasエナジードリンク!?恐ろしいノベルティだ。エナジーが尽きてもsasを書けということか(個人の見解です)

ぶっちゃけ今年はあまり発表するつもりはなかったが、初参加の後輩が発表すると言っているのに見捨てるわけにはいかないと思って急遽発表資料をこしらえた。かつて私が初めて発表する際には偉い人が二人も登壇していたことに随分助けられたので、今度は自分の番がきたというわけだ。自己満の領域だが私には発表登録する十分な理由だった。急遽決めたのであらゆる申請がぎりぎりだったがよく間に合った。多大なご迷惑をおかけしたことでしょう…ありがとうございました…

今年の発表も面白そうなのが多かった。文字コード、dataset-json、グラフ軸目盛の自動調整、SASでゲーム…sasでゲームの発表はぜひ聞きたかったが2日目は諸般の事情により午前で引き上げざるを得なかった。後日発表資料を読むもまあ内容にピンと来ない。ある程度powershellは触ったことがあるので何となくわかるかなーと思いきや全然である。まだまだ自分のpowershell力が足りないな…これでは立派なpowershellおじさんを名乗れないではないか。名乗る必要があるのか?pythonでも書いてろ。

なんにせよ今年のユーザー会も無事終わって何より。終わってからしばらくは咳が止まらずとんでもない体調不良に見舞われたがそれも無事収まってよかった。息か咳かどっちしてるのかわからん位の状態になるのは本当に大変だった。久しぶりの遠出に肉体が付いていかなかったのだろう。あまりにも貧弱な体には困ったものだ。毎年恒例だが来年の発表のめどが何もついていないのでこちらもどうしたものやら。結局発表するにしても締め切りぎりぎりに登録することになるのだろう…


2024年8月1日木曜日

最近使っているeditorをVSCODEに移行した話

 もともとプログラムを書くのにバキバキに改造した秀丸エディタを使っていたが、最近有識者の手助けもありVSCODEに移行した。基本的に便利。ちょっと文字コードの融通が利かないことがあるが多分私が上手に使えていないだけで良い方法があるんだと思う。VSCODEといえば拡張機能をはじめとした種々の昨日の豊富さが売りなので、私がよく使っている機能を紹介する。あまりにもキーボードショートカットが多すぎて全然把握しきれないし、とりあえずで登録しようとしたら大体何かと衝突すると警告される。

キーボードショートカット

  • ctrl+shift+[: 今カーソルが当たっている個所のインデントを折りたたむ
  • ctrl+shift+]: 今カーソルが当たっている個所のインデントを展開する
  • ctrl+shif+fでgrep検索 …ただし事前にVSCODEでフォルダを開いている必要がある
    • 検索結果から除外するファイル/選択するファイルを正規表現で指定できるので、とりあえず検索対象に*.sasを選択している。この辺の設定は前回の指定を結構覚えているので頻繁に指定しなくても良いので助かっている
    • grep検索した後alt+enterすると検索結果を新規editorを立ち上げて表示してくれる
    • grep検索の結果をサイドバーに出すときは標準で展開された状態だが、右上の端のアイコンを押すと全部折りたたんでくれる
      • 標準で折りたたんだ状態で出してくれる設定とかないんかな。多分あるんだろう
拡張機能
  • SASの公式 
    • これがあるとプロシジャなどの入力補完からハイライトまでしてくれるので必須。設定を頑張ればVSCODE上でSASを動かせるらしいがそこまでは試していない
  • VSCODE日本語化
  • alignment
    • 指定した範囲を事前に指定したキー文字列で縦にそろえてくれる拡張
    • 設定のjsonファイルを開けて、カンマをキー文字列に追加して、要らないキー文字列を削除した後、F1のコマンドパレットからalign all charsするかalt+;で実行
    • setting jsonは左下の歯車→設定→拡張機能→alignment configurationからsetting jsonファイルを開けて中のalignment.charを修正すればキーの指定が可能。 私は; , then,=を指定している

例えば以下のようなカンマ区切りの文字列を、カンマの位置を揃えるように縦に整形する
a,b,c
12,34,56
a  ,b  ,c
12,34,56

その他
SASの関数や引数の補完はSASの公式拡張がやってくれるので、ユーザースニペットを現在の日付や名前などの定型文挿入に使っている。挿入するユーザースニペットは設定のSAS.jsonに指定しているので、SASファイル以外では余計なスニペットを起動しないのが非常に便利。
例えば以下のように、todayと入力すると現在の年月日がハイフン区切りで入力されるものを設定している
  "today":{
        "prefix": "today",
        "body": ["$CURRENT_YEAR-$CURRENT_MONTH-$CURRENT_DATE"] ,
        "description": "today",
    }

ctrl+@で画面下部でコンソールを起動して、そこでpowershellを操作できる。SAS書いているときに使うことはあまりないのだが、データを見ながら手元のeditorで簡単な計算ができるのは結構便利。例えば詳細な指定はできないが2つの日付の間の日数を手元で出すことができるのも結構助かっている。以下のようにすれば前の日付から後ろの日付までの期間を出してくれる。もちろん四則演算も可能。
new-timespan "2022/03/13" "2023/04/14" | format-table -property days 
この下部コンソールのpowershellはVSCODEで開けているフォルダを現在のディレクトリと認識してくれるので、簡単なものなら適当に別フォルダでも使いまわせてしまうのもgood

行全体ではなく矩形選択はctrl+shift+alt+矢印で指定する。これは押すキーが多くてちょっと押しにくく不便。4キー押しはさすがに無理なのでキーバインドを変更したいが良い感じのものが大体既存の設定と競合するので変えれていない。

選択箇所を全て大文字に変換するのは標準だとどのコマンドか忘れてしまった。私はalt+uに割り当てを早々に変えてしまった。

以上が何となく私が使っている設定の一部だ。あまりにも豊富すぎてまだ把握できていない。これからもVSCODEを利用して仲良くなれるようしていきたいと思うが、今まで使っていた秀丸エディタも便利なので場合によって使い分けていきたい。あまりにも融通の利く秀丸マクロの完全な移行が出来ていないので…多分完全に置き換えるのは無理だろうなあ…


2024年7月1日月曜日

sasで変数の和を計算する話

 同じobsの二個以上の変数の和を求めるときは、sum関数を使うか変数を+で足すかのどちらかです。どちらも似たような処理ですが、書き方で微妙に欠損の取り扱いが違うので注意が必要です。足す変数に欠測が含まれるときはsum関数は欠測を飛ばして足し算して、+で足す時は足し算そのものが行われません。

3157  data _null_ ;
3158  a = 2 ; b = . ; c = a+b ;  putlog c= ; output ;
3159  a = 2 ; b = . ; c = sum(a,b) ; putlog c= ; output ;
3160
3161  run ;

c=.
c=2
NOTE: 欠損値を含んだ計算により、以下の箇所で欠損値が生成されました。
      (回数)(行:カラム)
      1 3158:22
NOTE: DATAステートメント処理(合計処理時間):
      処理時間           0.00 秒
      CPU時間            0.00 秒

出てるlogは読もうね。欠損の処理がめんどくさいしNoteだからと欠損値を含んだ計算…をlogに残したままにするとこの手の結果が変わるやつを見逃すから、この手のはできればlogに残さないようにしてね。
あと誰かのを引き継いだ時に欠損値を含んだ計算…のlogが残っていると何がどうなってるのかの確認を全部しないといけないからね。出来ればlogに残さないようにしてね(憤怒)

2024年6月1日土曜日

excel日付とsas日付の違いの話

excel日付とSAS日付はどちらも日付を数値にしたものですが、そういえばこの二つは開始日が違ったな…ということがありましたので、忘れないように記事にします。こんな事めったにないとは思いますが。

この上記のexcelは、1行目に変数ラベル、2行目の変数名、3行目に日付(excel日付)が格納されています。これをsasにimportすると以下のようになります。仮なので読み込む際にオプションのgetnamesをyesにしたとしています。

データとしてはexcel日付の列ですが、変数名がデータの値として格納されているので文字列として扱われた結果2024/5/2がexcel日付のまま45414として文字列になっています。ところで2024/5/2のsas日付は23498なのでこのまま日付を型変換すると2024/5/2になりません。45414は2084/5/3です。

11   data _null_ ;
12       a = '02may2024d'd ;
13       putlog a= ;
14   run ;

a=23498

excel日付は1が1900-1-1なのに対し、SAS日付は1が1960-1-2なので60年と1日の差があります。ちなみにSAS日付上での1960-1-1は0です。excel日付は1始まりですがSAS日付は0始まりということもこの時初めて知りました。

なのでexcel日付からSAS日付に変換する際には1900-1-1と1960-1-2の差分の(21915 + 1)をexcel日付側から引けば日付が一致します。以下の実行ログを見ると、引き算した後のEXDTには正しく2024-5-2が格納されていて、excelから読み込んだものをそのままformat当てたORGDTは2084-5-3となっています。

130
131  data _null_ ;
132      set sh1 ;
133
134      format EXDT  yymmdd10. ;
135      format ORGDT yymmdd10. ;
136
137      if _n_ = 2 then do ;
138          ORGDT = label ;
139          EXDT = label - (21915 + 1) ;
140
141          putlog ORGDT= EXDT= ;
142      end ;
143
144  run ;

NOTE: 以下の箇所で文字値を数値に変換しました。(行:カラム)

      138:17   139:16

ORGDT=2084-05-03 EXDT=2024-05-02

NOTE: データセットWORK.SH1から2オブザベーションを読み込みました。

NOTE: DATA ステートメント処理(合計処理時間):

      処理時間           0.00 秒

      CPU時間            0.00 秒

普段こんなことはほとんど起こらないのですが、読み込むexcelファイルの日付がexcel日付で入力されている+その列にexcel日付以外の文字列が存在することで今回のようなことが起こります。例えば今回のような1行目が変数ラベルで2行目が変数名になっていたりとか、SASで取り込む際には不要ですけどファイルの作成者名が上の方に入ってたりとか、で紛れ込んできます。読み込むexcelをきれいに加工してからSASにimportすれば良いのですが、あまりexcelに変に手を加えるのも憚られる時があるし…で難しいところです。

2024年5月1日水曜日

階層構造をもったjsonをSASに読み込む話

 少し前(2019年は"少し"前です)のSASユーザー会で、jsonに対応したLibnameステートメントを使って単階層のJSONをSASに読み込む内容の発表がありました。…そういえば複数階層を持つjsonをSASで読み込むとどうなるのかって気になりますよね。私はなりました。時間が空いていますがちょっと調べたので記事にします。件のSASユーザー会の資料は何となく怖いのでリンクしません。「JSONという奇妙な拡張子とSAS」で調べてみてください。HITすると良いんですが。

用意したのは以下の構造のjsonです。このブログは容赦なくベタ張りするのでスクロールが大変ですね。すみません。改善する気は今のところありません。例えばid:1は子階層childrenを持っています。

{

  "id": "1",
  "name": "root",
  "children": [
    {
      "id": "2",
      "name": "child1",
      "Detail": [
        {
          "id": "3",
          "name": "grandchild1",
          "items": [{"itemID": "1A", "itemprice": 280}]
        },
        {
          "id": "4",
          "name": "grandchild2",
          "items": []
        }
      ]
    },
    {
      "id": "5",
      "name": "child2",
      "Detail": [
        {
          "id": "6",
          "name": "grandchild3",
          "items": [{"itemID": "1B", "itemprice": 500}]
        }
      ]
    }
  ]
}

これをSAS以下のプログラムでSASに読み込みます。encodingをutf-8にしているのは何となくです。このデータはシングルバイトのみなので違いはありません。

filename TG "piyopiyo\Hierarchy.json" encoding="utf-8" ;

libname IN json fileref = TG ;

proc copy in = IN out = WORK ; run ;

libname IN clear ;

読み込むと以下の通りAllData、Children、Children_detail、Detal_items、rootのデータセットになります。


それぞれが各階層のデータに対応していますが、階層間のつながりはAllDataを見ればわかるようになっています。各階層が縦に積まれているので、実際には転置したほうが使いやすいかもしれません。

以下の画像はAlldataデータセットの内容で、例えば1階層目にはidが1、NameがRoot、子階層としてChildrenを持っていて、2階層目のChildrenはidが2、nameがchild1で子階層(1階層目から見たら孫階層)としてDetailを持っている、ことなどがわかります。

Libnameでとりあえず読み込んだだけにしては階層の情報も含めていい感じに取得できていると思います。SASが自動で作成するmapファイルもなかなかのもんじゃないですか。



2024年4月1日月曜日

SASの勉強会に行ってきた話

先日某所にてSASの某発表会に参加した。開催当初から参加しているが、ずいぶん大所帯になったものだ。すげーわ。これが主催者の某氏の人徳かと恐れ入るばかり。最初は4人だか5人だかくらいだったのが今は40弱て。 

私の発表資料はこちら。今回はproc sgpie…またこいつグラフ書いてんな。他にやることないんか。円グラフについてのプロシジャを紹介する内容だ。GTLで良くない?みたいな正論パンチはご遠慮いただきたく。何の反論もございません。この資料は例によってマイクロソフトのswayを使っている。発表に使ったPPTを雑に公開するにはこれ以上ない便利ツールなんだが私以外の人が使っているのを見たことがない。お願いだからマイクロソフト君はこんな便利なサービスを終えないでくれ。

10分程度の短い発表とはいえ10本強の発表を聞くのはすごいカロリーを要する。どれも面白くて興味深いのだが。ワーッと発表がきてうわーっとなるのはSASユーザ会みたいな30分と発表の枠の大きなところでは味わえない醍醐味か。どちらもとても楽しい。

関係者各位の多大なご厚意によってこの勉強会は成り立っています。みなさままことにありがとうございました。